图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)

这篇具有很好参考价值的文章主要介绍了图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

图像二值化处理

二值化原理

图像二值化就是把让图像的像素点只有0和1(只有黑白两各种颜色,黑是背景,白是前景),关键点是寻找一个阈值T,使图像中小于阈值T的像素点变为0,大于T的像素点变为255。下面介绍的就是寻找一个图像的阈值T的方法。(主要根据直方图)

API介绍

retval = cv2.threshold(src, des, thresh, maxval, type)
  • retval:返回的阈值(double类型)
  • dst:阈值分割结果图像(也可以写到函数参数里面)
  • src:原图像, 可以是多通道的
  • thresh:要设定的阈值
  • maxval:当type类型是THRESH_BINARY时,需要设定的最大值
  • type:阈值分割的方式(也正是type的不同导致了有多种方法)

手动设置阈值

均值法

利用图像像素点的平均值作为二值化处理的阈值。需要手动找到图像像素点的平均值,然后作为API的阈值传入,代码如下:

  #include<opencv2/opencv.hpp>
    #include<iostream>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
    	Mat src = imread("C:\\Users\\86151\\Desktop\\opencv\\picture\\4.jpg");
    	Mat src_gray;//装灰度图像
    	Mat src_thres;//来装二值化的图像
    	if (src.empty())
    	{
    		cout << "no picture" << endl;
    		return -1;
    	}
    	imshow("src", src);
    	//对图像进行灰度处理
    	cvtColor(src, src_gray, COLOR_BGR2GRAY);
    	imshow("GRAY", src_gray);
    	//得到像素点平均值
    	Scalar m = mean(src_gray);//mean函数就是求图像像素点平均值的函数,返回值是Scalar类型
    	//进行二值化处理
    	threshold(src_gray, src_thres, m[0], 255, THRESH_BINARY);//255是最大值
    	imshow("threshold", src_thres);
    	waitKey(0);
    	return 0;
    }

二值化效果如下:
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)

迭代法

迭代法是均值法的升级版:

1.选取初试分割阈值,一般初始为图像灰度值的平均值T

2.根据阈值T将图像分割为前景和背景(大于阈值为前景,小于为背景),分别求出两者的平均值T0和T1

3.计算新阈值T2 = (T0 + T1)/ 2

4.若T == T2,那么最终阈值就是T2,否则T = T2,再次从2开始。

代码如下:

T=img.mean()

def ThresholdIteration(T,img):
    while True:
        T0=img[img>T].mean()
        T1=img[img<=T].mean()
        t=(T0+T1)/2
        if T==t:
            return T
        else:
            T=t
T=int(ThresholdIteration(T,img))
th,img_bin = cv.threshold(img,T,255,cv.THRESH_BINARY)
print(f'Thrshold is {th}')
show(np.hstack([img,img_bin]))

自动设置阈值

直方图法

直方图法就是默认阈值参数是125,适合于双峰直方图图像,代码如下:

   #include<opencv2/opencv.hpp>
    #include<iostream>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
    	Mat src = imread("C:\\Users\\86151\\Desktop\\opencv\\picture\\4.jpg");
    	Mat src_gray;
    	Mat src_thres;
    	if (src.empty())
    	{
    		cout << "no picture" << endl;
    		return -1;
    	}
    	imshow("src", src);
    	//对图像进行灰度处理
    	cvtColor(src, src_gray, COLOR_BGR2GRAY);
    	imshow("GRAY", src_gray);
    	//得到像素点平均值
    	Scalar m = mean(src_gray);
    	//进行二值化处理
    	threshold(src_gray, src_thres, 125, 255, THRESH_BINARY);//更改的地方
    	imshow("threshold", src_thres);
    	waitKey(0);
    	return 0;
    }

结果如下:
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)

全局阈值法

OTSU法

OTSU法是现在最常用也是准确度较高的算法:区别就是再threshold函数的type中加上关键词即可,阈值处手动设置为0,代码如下:

  threshold(src,des,0,255,THRES_BINARY | THRES_OTSU)

原理如下:
假设一个图像的直方图如图所示(原本前景、背景像素直方图是一个图,假设2为阈值的话就会区分前景和背景,如图所示,这是假设的情况,后续opencv会从0到5这留个区间都假设一遍)
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)
opencv要计算的对象有背景像素直方图和前景像素直方图,两者横区间是0 1 2 3 4 5这六区间。

首先面对背景像素直方图:

1.opencv计算权重W = (8 + 7 + 2)/ 36,36是整个直方图(包括前景和后景)的像素值的和,根据图像可以计算出这六个数字相加为36。

2.计算 0 1 2这三个区间的加权平均值u = (0 * 8 + 1 * 7 + 2 * 2 )/ 17 = 0.6471。

3.计算背景像素直方图的方差:
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)至此,背景像素直方图计算完毕,按照同样的方法计算前景像素直方图:
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)
然后按照两图的权重和方差进行权重运算(类内方差):
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)
得到一个最终数值。这只是假设2为阈值的情况,实际上opencv会从0 - 5都假设一遍,都计算出这样的最后结果,

选取结果最小的点作为实际的阈值。这就是OTSU算法查找阈值的原理。

实际结果(代码换掉threshold函数这一行就可以了):
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)

三角形法

三角形法适应于单峰直方图,若图像直方图如下(蓝色的线):
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)
那么三角形法就是选择直方图的最低点和最高点连一条线,然后在直方图的边上找一点使之距离我们所画的这一条线最远,标记为点O,那么点O的横坐标就是实际的阈值,效果如下:
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)
代码如下:

threshold(src,des,0,255,THRES_BINARY | THRES_TRIANGLE)

自适应阈值法

有时候一张图片有些地方很暗,有些地方很亮,那样继续使用全局阈值的话,会导致图像二值化不合理,比如:
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)
使用OTSU算法处理后的二值化图像,可见有些部分变黑了,这不是我们想要的结果,这个时候就要用到自适应阈值处理方法了,自适应阈值分割则将图像分成很多个小块,对每个小块单独计算其阈值,然后用这个计算得到的阈值对该小块进行分割,这样的好处是,即使受到光照影响,某一块较暗或较亮,但是可以单独计算这一块的合理阈值来进行分割而不用使用全局的固定阈值,换句话说,亮的小块对应的阈值较大,暗的小块对应的阈值较小,从而可以达到很好的分割效果。

API
adaptiveThreshold( src, des,maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])
第一个参数:InputArray类型的src,输入数组,必须为单通道,8位或32位的浮点型Mat即可。
第二个参数:OutputArray类型的dst,与输入有一样的尺寸和类型。
第三个参数:double类型的maxval,给像素赋的满足条件的非0值。
第四个参数:int类型的adaptiveMethod,指定要使用的自适应阈值算法,可取值为ADAPTIVE_THRESH_MEAN_C或ADAPTIVE_THRESH_GAUSSIAN_C
第五个参数:int类型的thresholdType,阈值类型,必须为THRESH_BINARY或THRESH_BINARY_INV。
第六个参数:int类型的blocksize,用于计算阈值大小的一个像素的邻域尺寸,取357等。
第七个参数:double类型的C,减去平均或加权平均值后的常数值,通常为正数。

使用代码如下:

 adaptiveThreshold(src_gray, src_thres, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 7, 4);//注意:输入是灰度图像

效果如下:
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)

绘制图像直方图

  #include<opencv2/opencv.hpp>
    #include<iostream>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
    	Mat src = imread("C:\\Users\\86151\\Desktop\\opencv\\picture\\4.jpg");
    	Mat src_gray;
    	if (src.empty())
    	{
    		cout << "no picture" << endl;
    		return -1;
    	}
    	imshow("src", src);
    	cvtColor(src, src_gray, COLOR_BGR2GRAY);
    	imshow("GRAY", src_gray);
    	//绘制直方图
    	Mat src_hist;
    	const int a = 256;
    	float bin_range[2] = { 0,255 };
    	const float* range[1] = { bin_range };
    	calcHist(&src_gray, 1, 0, Mat(), src_hist, 1, &a, range, true, false);
    	//绘制直方图的画布
    	int hist_w = 500;
    	int hist_h = 400;
    	int hist_bin = cvRound((double)hist_w / a);
    	Mat hist_canvas = Mat::zeros(hist_h, hist_w, CV_8UC3);
    	//对直方图数据进行归一化
    	normalize(src_hist, src_hist, 0, 255, NORM_MINMAX, -1, Mat());
    	//将直方图以折线统计图的方式花在画布上
    	for (int i = 1; i < 256; i++)
    	{
    		line(hist_canvas, Point(hist_bin * (i - 1), hist_h - cvRound(src_hist.at<float>(i - 1))),
    			Point(hist_bin * (i), hist_h - cvRound(src_hist.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);
    	}
    	imshow("src_hist", hist_canvas);
    	waitKey(0);
    	return 0;
    }

结果如图:
图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)

SERENDIPITY文章来源地址https://www.toymoban.com/news/detail-474062.html

到了这里,关于图像二值化处理(全局阈值 自适应阈值 手动阈值操作以及直方图画法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图像二值化阈值调整——cv2.threshold方法

    二值化阈值调整:调整是指在进行图像二值化处理时,调整阈值的过程。阈值决定了将图像中的像素分为黑色和白色的界限,大于阈值的像素被设置为白色,小于等于阈值的像素被设置为黑色。 首先画出灰度直方图:横坐标是灰度值0—255,纵坐标是该灰度值的像素个数。 方

    2024年02月06日
    浏览(40)
  • 【Opencv--自适应图像二值化】cv2.adaptiveThreshold()

    在这里 cv2.threshold函数 介绍了普通的opencv图像阈值处理函数。但threshold 的图像阈值处理对于某些光照不均的图像,这种全局阈值分割的方法并不能得到好的效果。 图像阈值化操作中,我们更关心的是从二值化图像中分离目标区域和背景区域,仅仅通过固定阈值很难达到理想

    2024年02月07日
    浏览(30)
  • 【GEE笔记】最大类间方差法(otsu、大津法)算法实现——计算阈值、图像二值化分割

    1、最大类间方差法原理概述 2、GEE频率分布统计,直方图绘制 3、算法具体实现,以GEE JavaScript版本为例 4、目标像元提取,以遥感影像提取水体为示例 最大类间方差法(又名otsu、大津法)是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法。算法假定该图像根据

    2024年02月06日
    浏览(39)
  • [2] 图像处理之----二值化处理

    简单阈值是选取一个全局阈值,然后把整幅图像分成非黑即白的二值图像,灰度值大于阈值就赋为255反之为0。 ret,mask = cv2.threshold(img2gray,175,255,cv2.THRESH_BINAR) 返回值一: 阈值,(Otsu‘s二值化会用到) 返回值二: 处理以后的图像 参数一: 初始图像 参数二:我们自己设定的阈

    2024年02月05日
    浏览(36)
  • OpenCV图像处理----图像的二值化

    图像二值化( Image Binarization) 就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。 二值化的原理 OpenCV提供的图像二值化API threshold()方法参数: 图片矩阵 阈值 图片中的最大值 二值化的方式 二值化的方式: THRESH_BINARY 高于阈值改为

    2024年02月12日
    浏览(31)
  • 图像像素操作与二值化

    目录 1、图像像素比较 1.1 比较函数  1.2 图像最大值最小值寻找 2、图像像素逻辑操作 3、图像二值化 3.1 固定阈值二值化 3.2 自适应阈值二值化 1.1 比较函数  1.2 图像最大值最小值寻找         3.1 固定阈值二值化     3.2 自适应阈值二值化  

    2024年02月12日
    浏览(30)
  • MATLAB 图像处理 (二值化,image图片黑白处理)

    Q: MATLAB如何将图片进行 二值化 ,并将 二值化后图片 中的 黑色变成白色 , 原本的白色保持不变,黑白之间的黑色轮廓保持不变。 A: 使用 MATLAB 中的 imbinarize 函数 进行图片二值化。将指定阈值以下的像素值设为 0,其他像素值设为 1。 然后可以使用逻辑取反运算符 ~ (波浪线

    2023年04月08日
    浏览(28)
  • 基于opencv的c++图像处理(图像二值化)

    基于opencv的c++接口,实现常用的图像二值化方法,包括了最大类间方差法(OTSU)、固定化阈值以及自适应阈值。 该函数将固定级别的阈值应用于多通道阵列。该函数通常用于从灰度图像中获取双层(二进制)图像(#compare 也可用于此目的)或用于去除噪声,即过滤掉值过小

    2024年02月07日
    浏览(32)
  • OpenCV常用功能——灰度处理和图像二值化处理

    1.1 cvtColor函数 函数原型: 功能 :转换图像颜色空间。 参数 : src: 输入图像。 code: 颜色空间转换代码。可以取常量cv2.COLOR_BGR2GRAY或cv2.COLOR_RGB2GRAY。 dst: 输出图像。 dstCn: 输出图像的通道数,如果设置为0,则跟随转换代码自动设置。 内置函数示例代码: 灰度处理的原理是将

    2024年02月08日
    浏览(47)
  • FPGA|数字图像处理实现口罩识别——二值化

    【写在前面】刚入门小菜鸟,记录一下口罩识别学习过程。参考文件和网址会在文末注明。有错误欢迎指出,也欢迎进行补充~ 原理图如下,二值化对应为红框里的部分 使用的二值化方法是 手动指定一个 阈值 ,通过阈值来进行二值化处理 。(还有一种方法是一个自适应阈值

    2023年04月11日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包