C/C++开发,opencv阀值操作

目录

一、OpenCV-阀值操作

1.1阀值操作函数threshold

1.2threshold的操作类型

1.3Otsu算法

二、样例开发

2.1 Makefile

2.2 main.cpp

2.3 运行效果

三、OpenCV-自适应阀值操作

        3.1 自适应阀值操作函数-adaptiveThreshold

3.2 样例开发


一、OpenCV-阀值操作

1.1阀值操作函数threshold

        在OpenCV中,阀值操作是一种基本的图像处理方法,用于将灰度图像转换为二值图像。这个操作是通过使用一个设定的阈值(thresh)来比较输入图像的每个像素值,并根据比较结果将像素值设置为0或最大值(maxval)。有五种不同的阀值操作类型,包括二进制阀值化、反二进制阀值化、截断阀值化、阀值化为0、反阀值化为0。

        在OpenCV-C++源码中,其阀值操作函数定义在\opencv2\imgproc.hpp中:

@param src input array (multiple-channel, 8-bit or 32-bit floating point).
@param dst output array of the same size  and type and the same number of channels as src.
@param thresh threshold value.
@param maxval maximum value to use with the #THRESH_BINARY and #THRESH_BINARY_INV thresholding
types.
@param type thresholding type (see #ThresholdTypes).
@return the computed threshold value if Otsu's or Triangle methods used.

@sa  adaptiveThreshold, findContours, compare, min, max
 */
CV_EXPORTS_W double threshold( 
    InputArray src, 
    OutputArray dst,         
    double thresh, 
    double maxval, 
    int type );

        该函数threshold将固定级别的阈值设置应用于多通道阵列。该函数通常用于从灰度图像中获得双层(二进制)图像或用于去除噪声,即过滤掉太小或太大的像素价值观该函数支持多种类型的阈值处理。它们由类型参数。此外,特殊值#THRESH_OTSU或#THRESH-TRIANGLE可以与以上值。在这些情况下,函数使用Otsu或三角算法,并使用它来代替指定的阈值。注意:目前,Otsu和Triangle方法仅适用于8位单通道图像。

1.2threshold的操作类型

        如果对卷积核有所了解的话,也可以把阀值操作看做是一个用1*1的核进行卷积,对每个像素进行一次非线性操作。

        在OpenCV中,阀值操作有五种类型(int type),分别是:

  1. THRESH_BINARY = 0:二值化,大于阈值的为255,小于阈值的为0。
  2. THRESH_BINARY_INV = 1:反二值化,大于阈值的为0,小于阈值的为255。
  3. THRESH_TRUNC = 2:截断法,大于阈值的取阈值,小于阈值的不变。
  4. THRESH_TOZERO = 3:大于阈值的不变,小于阈值的为0。
  5. THRESH_TOZERO_INV = 4:大于阈值的为0,小于阈值的不变。

        在使用时可以根据实际需求选择相应的类型。

1.3Otsu算法

        函数cv::threshold可以自动决定最优的阀值,只需要对参数thresh传递THRESH_OTSU。Otsu算法是一种确定图像二值化最优阈值的算法,其原理是利用最大类间方差法来确定图像的阈值,从而将图像分割成前景和背景两部分。

        Otsu算法的基本思想是:假设输入图像的高为、宽为,代表其归一化所获得的图像灰度直方图,代表灰度值等于的像素点的个数在图像中占的比例。首先,计算灰度直方图的零阶累积矩(也称为累加直方图)和一阶累积矩;然后,计算图像总体的灰度平均值,其实就是时的一阶累积矩;接着,对于每个灰度级作为阈值,计算前景区域的平均灰度、背景区域的平均灰度和整幅图像的平均灰度的方差,对方差的衡量采用以下度量;最后,找到使类间方差最大时的对应的灰度级作为最优阈值。

        Otsu算法是一种自适应阈值确定的方法,计算简单,效率高,但对于光照不均的图像处理效果不是很好。

二、样例开发

2.1 Makefile

关于opencv编辑及库生成、调用等请参考本专栏的前面博文,这里不展开。    编译命令:mingw32-make -j4或make -4。

#/bin/sh
CX= g++ 

BIN 		:= ./
TARGET      := transform_img1.exe
FLAGS		:= -std=c++11 -static
SRCDIR 		:= ./
#INCLUDES
INCLUDEDIR 	:= -I"../../opencv_MinGW/include" 
#-I"$(SRCDIR)"
staticDir   := ../../opencv_MinGW/x64/mingw/staticlib/
#LIBDIR		:= $(staticDir)/libopencv_world460.a\
#			   $(staticDir)/libade.a \
#			   $(staticDir)/libIlmImf.a \
#			   $(staticDir)/libquirc.a \
#			   $(staticDir)/libzlib.a \
#			   $(wildcard $(staticDir)/liblib*.a) \
#			   -lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid 
#opencv_world放弃前,然后是opencv依赖的第三方库,后面的库是MinGW编译工具的库

LIBDIR 	    := -L $(staticDir) -lopencv_world460 -lade -lIlmImf -lquirc -lzlib \
				-llibjpeg-turbo -llibopenjp2 -llibpng -llibprotobuf -llibtiff -llibwebp \
				-lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid 
source		:= $(wildcard $(SRCDIR)/*.cpp) 

$(TARGET) :
	$(CX) $(FLAGS) $(INCLUDEDIR) $(source)  -o $(BIN)/$(TARGET) $(LIBDIR)

clean:
	rm  $(BIN)/$(TARGET)

2.2 main.cpp

#include "opencv2/opencv.hpp" //Include file for every supported OpenCV function 
#include <iostream>
#include <vector>
using namespace std;
//阀值化
void sum_rgb1( const cv::Mat& src, cv::Mat& dst )
{
	// Split image onto the color planes
	//
	vector< cv::Mat> planes;
	cv::split(src,planes);
	cv::Mat b = planes[0],g = planes[1],r = planes[2],s;
	// Add equally weighted rgb values
	//
	cv::addWeighted( r,1./3., g,1./3., 0.0,s );
	cv::addWeighted( s,1., b,1./3.,0.0,s );
	// Truncate values above 100
	//
	cv::threshold( s,dst,100,100,cv::THRESH_TRUNC );
}
//组合与阀值图像平面
void sum_rgb2( const cv::Mat& src,cv::Mat& dst )
{
	// Split image onto the color planes
	//
	vector<cv::Mat> planes;
	cv::split(src,planes);
	cv::Mat b = planes[0],g = planes[1],r= planes[2];
	// Accumulate separate planes, combine and threshold
	//
	cv::Mat s = cv::Mat::zeros(b.size(),CV_32F);
	cv::accumulate(b,s);
	cv::accumulate(g,s); 
	cv::accumulate(r,s);
	// Truncate values above 100 and rescale into dst.
	cv::threshold( s,s,100,100,cv::THRESH_TRUNC );
	s.convertTo(dst,b.type());
}

void help()
{
	cout <<"Call: ./1.PNG"<< endl;
	cout << "Shows use of alpha blending (addweighted) and threshold" << endl;
}

int main(int argc,char** argv){
	help();
	if(argc< 2){ cout <<"specify input image" << endl; return -1;}
	// Load the image from the given file name
	//
	cv::Mat src = cv::imread( argv[1] ),dst;
	if( src.empty() ){
		cout << "can not load " << argv[1] << endl; 
		return -1;
	}
	// sum_rgb1( src,dst);
	sum_rgb2( src,dst);
	// Create a named window with the name of the fle and
	// show the image in the window1
	cv::imshow( argv[1],dst );
	// Idle until the user hits any key
	//
	cv::waitKey(0);
	return 0;
}

2.3 运行效果

三、OpenCV-自适应阀值操作

        3.1 自适应阀值操作函数-adaptiveThreshold

        自适应阀值操作adaptiveThreshold和前面的阀值化方法不同,其阀值在整个过程中自动产生变化。同样在在\opencv2\imgproc.hpp中定义。在OpenCV中,自适应阈值操作是一种更为高级的阈值处理方法,用于处理具有非均匀亮度的图像。自适应阈值操作的基本思想是:对于每个像素,都使用其邻域的像素值来计算其阈值。这个邻域的像素值通常包括该像素周围的8个或16个像素。这种方法的优点是能够更好地适应图像的非均匀亮度。

@param src Source 8-bit single-channel image.
@param dst Destination image of the same size and the same type as src.
@param maxValue Non-zero value assigned to the pixels for which the condition is satisfied
@param adaptiveMethod Adaptive thresholding algorithm to use, see #AdaptiveThresholdTypes.
The #BORDER_REPLICATE | #BORDER_ISOLATED is used to process boundaries.
@param thresholdType Thresholding type that must be either #THRESH_BINARY or #THRESH_BINARY_INV,
see #ThresholdTypes.
@param blockSize Size of a pixel neighborhood that is used to calculate a threshold value for the
pixel: 3, 5, 7, and so on.
@param C Constant subtracted from the mean or weighted mean (see the details below). Normally, it
is positive but may be zero or negative as well.

@sa  threshold, blur, GaussianBlur
 */
CV_EXPORTS_W void adaptiveThreshold( 
    InputArray src, 
    OutputArray dst,
    double maxValue, 
    int adaptiveMethod,
    int thresholdType, 
    int blockSize, 
    double C );

参数:
    src:输入图像,应该是灰度图像。
    dst:输出图像
    maxValue:输出图像的最大值。
    adaptiveMethod:自适应阈值算法的选择,可以是ADAPTIVE_THRESHOLD_MEAN_C或ADAPTIVE_THRESHOLD_GAUSSIAN_C。
    thresholdType:阈值类型,通常是THRESH_BINARY或THRESH_BINARY_INV。
    blockSize:用于计算阈值的邻域大小。
    C:加到阈值上的常数,以调整阈值。

        cv::adaptiveThreshold()根据adaptiveMethod的设置,允许两种不同的自适应阙值方法。两种方法都是逐个像素地计算自适应阙值T(x,y),方法是通过计算每个像素位置周围的b*b区域的加权平均值然后减去常数C,其中b由blocksize给定。不同的是,如果选择的均值方法是cv::ADAPTIVE THRESH MEAN C,那么均值时取得权值是相等的,如果选择的均值方法是cv::ADAPTIVE THRESH GAUSSIAN C(x,y)周围的像素的权值则根据其到中心点的距离通过高斯方程得到。
        对于thresholdType阈值类型来说 ,adaptiveThreshold函数的类型和threshold函数的类型相同。相对于一般的闽值化操作,当图像中出现较大的明暗差异时,自适应闽值时非常有效的。这个函数仅处理单通道8位或浮点型图像,并且要求源图像和目标图像不同。

3.2 样例开发

        Makefile文件,与前面的Makefile文件几乎一致,仅将输出程序名调整一下:

#TARGET      := transform_img1.exe
TARGET      := transform_img2.exe

       编译命令:mingw32-make -j4或make -4

        main.cpp实现

#include "opencv2/opencv.hpp" //Include file for every supported OpenCV function 

#include<iostream>
using namespace std;
int main( int argc,char** argv )
{
	if(argc != 7){ 
		cout <<"Usage:"<<argv[0] <<"fixed_threshold invert(0=offl1=on)"
		"adaptive_type(0=mean]1=gaussian) block_size offset image\n"
		"Example:"<<argv[0] <<"100 1 0 15 10 1.PNG"; 
		return -1;
	}
	// Command line
	double fixed_threshold = (double)atof(argv[1]);

	int threshold_type = atoi(argv[2]) ? cv::THRESH_BINARY : cv::THRESH_BINARY_INV;
	int adaptive_method = atoi(argv[3]) ? cv::ADAPTIVE_THRESH_MEAN_C : cv::ADAPTIVE_THRESH_GAUSSIAN_C;
	int block_size = atoi(argv[4]);
	double offset =(double)atof(argv[5]);
	cv::Mat Igray = cv::imread(argv[6], cv::IMREAD_GRAYSCALE);
	// Read in gray image
	//
	if( Igray.empty() ){ 
		cout << "Can not load " << argv[6] << endl; 
		return -1; 
	}
	// Declare the output images.
	//
	cv::Mat It,Iat;
	// Thresholds
	
	cv::threshold(
	Igray,
	It,
	fixed_threshold,
	255,
	threshold_type);
	cv::adaptiveThreshold(
	Igray,
	Iat ,
	255,
	adaptive_method,
	threshold_type,
	block_size,
	offset	);
	// Show the results.
	//
	cv::imshow("Raw",Igray);
	cv::imshow("Threshold",It);
	cv::imshow("Adaptive Threshold",Iat);

	cv::waitKey(0);
	return 0;
}

        运行效果如下:

猜你喜欢

转载自blog.csdn.net/py8105/article/details/133200475