资讯专栏INFORMATION COLUMN

【机器视觉学习笔记】大津法/Otsu最大类间方差法 最佳阈值处理(C++)

jackwang / 3146人阅读

摘要:当取最佳阈值时,两部分之间的差别应该是最大的。在算法中所采用的衡量差别的标准就是较为常见的最大类间方差。当所取阈值的分割使类间方差最大时,就意味着错分概率最小。

平台:Windows 10 20H2
Visual Studio 2015
OpenCV 4.5.3


本文所用源码修改自C++ opencv 图片二值化最佳阈值确定(大津法,OTSU算法)——Sharon Liu

概念

        Otsu算法,也叫最大类间方差法,是1979年由日本学者大津提 出的(所以也叫大津法),是一种自适应阈值确定的方法,是一种全局的二值化算法。
        它是根据图像的灰度特性,将图像分为前景背景两个部分。 当取最佳阈值时,两部分之间的差别应该是最大的。在Otsu算法中所采用的衡量差别的标准就是较为常见的最大类间方差。前景和背景之间的类间方差如果越大,就说明构成图像的两个部分之间的差别越大。
        当部分目标被错分为背景或部分背景被错分为目标,都会导致两部分差别变小。
        当所取阈值的分割使类间方差最大时,就意味着错分概率最小。

C++源码

OtsuThreshold

/******************************************************************************************Function:       OtsuThresholdDescription:	图片二值化最佳阈值确定(大津法,OTSU算法)Input:          src:原图片Return:         阈值******************************************************************************************/int OtsuThreshold(Mat src){	int threshold;	try	{		int height = src.rows;		int width = src.cols;		//histogram  		float histogram[256] = { 0 };		for (int i = 0; i < height; i++) 		{			unsigned char* p = (unsigned char*)src.data + src.step*i;			for (int j = 0; j < width; j++) 			{				histogram[*p++]++;			}		}		//normalize histogram  		int size = height*width;		for (int i = 0; i < 256; i++) 		{			histogram[i] = histogram[i] / size;		}		//average pixel value  		float avgValue = 0;		for (int i = 0; i < 256; i++) 		{			avgValue += i*histogram[i];		}		float maxVariance = 0;		float w = 0, u = 0;		for (int i = 0; i < 256; i++) 		{			w += histogram[i];			u += i*histogram[i];			float t = avgValue*w - u;			float variance = t*t / (w*(1 - w));			if (variance > maxVariance) 			{				maxVariance = variance;				threshold = i;			}		}	}	catch (cv::Exception e)	{	}	return threshold;}//————————————————//版权声明:本文为CSDN博主「Sharon Liu」的原创文章,遵循CC 4.0 BY - SA版权协议,转载请附上原文出处链接及本声明。//原文链接:https ://blog.csdn.net/sylsjane/article/details/80872744

主函数

图片路径根据实际情况调整,注意反斜杠是转义字符的开头,故“/”应替换为“//”

int main(int argc, char * argv[]){	Mat Image = imread("D://Work//OpenCV//Workplace//Test_1//1.jpg", 0);	int thresholdValue = OtsuThreshold(Image);	cout << "类间方差为: " << thresholdValue << endl;	Mat imageOutput;	threshold(Image, imageOutput, thresholdValue, 255, CV_THRESH_BINARY);	Mat imageOtsu;	threshold(Image, imageOtsu, 0, 255, CV_THRESH_OTSU); //Opencv Otsu算法	imshow("原图", Image);	imshow("Output Image", imageOutput);	imshow("Opencv Otsu", imageOtsu);	waitKey(0);	return 0;}

效果

原图

效果

OpenCv自带的Otsu算法结果,与上图一致

完整源码

#include #include #include using namespace cv;using namespace std;/******************************************************************************************Function:       OtsuThresholdDescription:	图片二值化最佳阈值确定(大津法,OTSU算法)Input:          src:原图片Return:         阈值******************************************************************************************/int OtsuThreshold(Mat src){	int threshold;	try	{		int height = src.rows;		int width = src.cols;		//histogram  		float histogram[256] = { 0 };		for (int i = 0; i < height; i++) 		{			unsigned char* p = (unsigned char*)src.data + src.step*i;			for (int j = 0; j < width; j++) 			{				histogram[*p++]++;			}		}		//normalize histogram  		int size = height*width;		for (int i = 0; i < 256; i++) 		{			histogram[i] = histogram[i] / size;		}		//average pixel value  		float avgValue = 0;		for (int i = 0; i < 256; i++) 		{			avgValue += i*histogram[i];		}		float maxVariance = 0;		float w = 0, u = 0;		for (int i = 0; i < 256; i++) 		{			w += histogram[i];			u += i*histogram[i];			float t = avgValue*w - u;			float variance = t*t / (w*(1 - w));			if (variance > maxVariance) 			{				maxVariance = variance;				threshold = i;			}		}	}	catch (cv::Exception e)	{	}	return threshold;}//————————————————//版权声明:本文为CSDN博主「Sharon Liu」的原创文章,遵循CC 4.0 BY - SA版权协议,转载请附上原文出处链接及本声明。//原文链接:https ://blog.csdn.net/sylsjane/article/details/80872744int main(int argc, char * argv[]){	Mat Image = imread("D://Work//OpenCV//Workplace//Test_1//1.jpg", 0);	int thresholdValue = OtsuThreshold(Image);	cout << "类间方差为: " << thresholdValue << endl;	Mat imageOutput;	threshold(Image, imageOutput, thresholdValue, 255, CV_THRESH_BINARY);	Mat imageOtsu;	threshold(Image, imageOtsu, 0, 255, CV_THRESH_OTSU); //Opencv Otsu算法	imshow("原图", Image);	imshow("Output Image", imageOutput);	imshow("Opencv Otsu", imageOtsu);	waitKey(0);	return 0;}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/120951.html

相关文章

  • 用JavaScript来计算两个图像的相似度

    摘要:最近看了阮一峰老师的相似图片搜索的原理二,其中介绍了通过内容特征法来对比两个图片的相似性。不知道是不是哪步出错了,感觉用这个方法计算出来的结果并不理想 最近看了阮一峰老师的相似图片搜索的原理(二),其中介绍了通过内容特征法来对比两个图片的相似性。 大致步骤: 把图片都缩放到50x50大小 转成灰度图片 利用大津法(Otsus method)确定阈值 通过阈值再对图片进行二值化 对比两...

    Leck1e 评论0 收藏0
  • OpenCV-自适应阈值函数cv::adaptiveThreshold

    摘要:类型的,输出图像。类型的,自适应阈值算法类型。为均值法获取阈值,为高斯窗加权和获取阈值。类型的,窗口的大小,只能为奇数。类型的,自适应阈值算法得到平均值或加权平均值后,再减的常数值。 作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 函数...

    fuchenxuan 评论0 收藏0
  • 2021-09-23 opencv学习笔记(图像变换,二值化,滤波器介绍及python实现)

    摘要:但是考虑一个双峰图像简单来说,双峰图像是一个直方图有两个峰值的图像。对于非双峰图像,二值化将不准确。在第三种情况下,我使用高斯核过滤图像以去除噪声,然后应用阈值。 ...

    CloudDeveloper 评论0 收藏0
  • opencv python 图像二值化/简单阈值化/大津阈值

    摘要:对于非双峰图像,二值化不准确。如果未使用阈值法,则与之前使用的阈值相同在第一种情况下,将全局阈值应用为值在第二种情况下,直接应用了的阈值在第三种情况下,使用高斯内核过滤图像以消除噪声,然后应用阈值处理代码 Image Thresholding 1简单的阈值化 cv2.threshold第一个参数是源图像,它应该是灰度图像. 第二个参数是用于对像素值进行分类的阈值, 第三个参数是max...

    luoyibu 评论0 收藏0
  • 机器学习实战_集成学习(一)

    摘要:集成学习集成学习通过构建并结合多个学习器来完成学习任务,比单一学习器获得显著优越的泛化性能。在此情形下,初始设置的学习轮数也许还远未达到,可能导致最终集成中只包含很少的基学习器而性能不佳。 集成学习 集成学习(ensemble learning)通过构建并结合多个学习器来完成学习任务,比单一学习器获得显著优越的泛化性能。想要获得好的集成,个体学习器应好而不同,要保证准确性和多样性。要产...

    MingjunYang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<