博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenCV+python:图像二值化
阅读量:3947 次
发布时间:2019-05-24

本文共 4269 字,大约阅读时间需要 14 分钟。

1,图像二值化概念及方法

一个像素点的颜色是由RGB三个值来表现的,所以一个像素点矩阵对应三个颜色向量矩阵,分别是R矩阵,G矩阵,B矩阵,它们也都是同样大小的矩阵。

在图像处理中,用RGB三个分量(R:Red,G:Green,B:Blue),即红、绿、蓝三原色来表示真彩色,R分量,G分量,B分量的取值范围均为0~255,比如电脑屏幕上的一个红色的像素点的三个分量的值分别为:255,0,0。

在理解了一张图片是由一个像素点矩阵构成之后,我们就知道我们对图像的处理就是对这个像素点矩阵的操作,想要改变某个像素点的颜色,我们只要在这个像素点矩阵中找到这个像素点的位置,比如第x行,第y列,所以这个像素点在这个像素点矩阵中的位置就可以表示成(x,y),因为一个像素点的颜色由红、绿、蓝三个颜色变量表示,所以我们通过给这三个变量赋值,来改变这个像素点的颜色,比如改成红色(255,0,0),可以表示为(x,y,(R=255,G=0,B=0))。

图像灰度化就是让像素点矩阵中的每一个像素点都满足下面的关系:R=G=B(就是红色变量的值,绿色变量的值,和蓝色变量的值,这三个值相等,“=”的意思不是程序语言中的赋值,是数学中的相等),此时的这个值叫做灰度值

二值化就是让图像的像素点矩阵中的每个像素点的灰度值为0(黑色)或者255(白色),也就是让整个图像呈现只有黑和白的效果。在灰度化的图像中灰度值的范围为0~255,在二值化后的图像中的灰度值范围是0或者255。

常用简单的二值化方法(还有很多):

方法1:
取阀值为127(相当于0~255的中数,(0+255)/2=127),让灰度值小于等于127的变 为0(黑色),灰度值大于127的变为255(白色),这样做的好处是计算量小速度快,但是 缺点也是很明显的,因为这个阀值在不同的图片中均为127,但是不同的图片,他们的颜色 分布差别很大,所以用127做阀值,白菜萝卜一刀切,效果肯定是不好的。
方法2:
计算像素点矩阵中的所有像素点的灰度值的平均值avg
(像素点1灰度值+…+像素点n灰度值)/ n = 像素点平均值avg
然后让每一个像素点与avg一 一比较,小于等于avg的像素点就为0(黑色),大于avg的 像 素点为255(白色),这样做比方法1好一些。
方法3:
使用直方图方法(也叫双峰法)来寻找二值化阀值,直方图是图像的重要特质。直方图方法 认为图像由前景和背景组成,在灰度直方图上,前景和背景都形成高峰,在双峰之间的最低 谷处就是阀值所在。取到阀值之后再一 一比较就可以了。
2,图像二值化代码实现
利用OpenCV的API进行二值化处理源代码:

import cv2 as cvimport numpy as npdef threshold_demo(image):                          #全局阈值    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)    ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_BINARY|cv.THRESH_OTSU)    print("threshold value %s"%ret)    cv.imshow("global_threshold_binary", binary)"""cv2.threshold函数是有两个返回值的,第一个返回值,得到图像的阈值,第二个返回值,也就是阈值处理后的图像,我们自己不一定能够找到一个最好的阈值,去二分化图像,所以我们需要算法自己去寻找一个阈值,而cv.THRESH_OTSU就可以满足这个需求,去找到一个最好的阈值。注意:他非常适用于图像灰度直方图具有双峰的情况,他会在双峰之间找到一个值作为阈值,对于非双峰图像,可能并不是很好用。因为cv.THRESH_OTSU方法会产生一个阈值,那么函数cv2.threshold的的第二个参数(设置阈值)就是0(None)了,并且在cv2.threshold的方法参数中还得加上语句cv2.THRESH_OTSU这里面第三个参数maxval参数表示与THRESH_BINARY和THRESH_BINARY_INV阈值类型一起使用设置的最大值。而我们使用的灰度图像最大则为255,所以设置为255即可THRESH_OTSU最适用于双波峰 THRESH_TRIANGLE最适用于单个波峰,最开始用于医学分割细胞等"""def local_threshold(image):                       #局部阈值    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)    binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)    cv.imshow("local_threshold_binary", binary)"""函数原型为:adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) -> dstsrc参数表示输入图像(8位单通道图像)。maxValue参数表示使用 THRESH_BINARY 和 THRESH_BINARY_INV 的最大值.adaptiveMethod参数表示自适应阈值算法,平均 (ADAPTIVE_THRESH_MEAN_C)或高斯(ADAPTIVE_THRESH_GAUSSIAN_C)。thresholdType参数表示阈值类型,必须为THRESH_BINARY或THRESH_BINARY_INV的阈值类型。blockSize参数表示块大小(奇数且大于1,比如3,5,7........ )。C参数是常数,表示从平均值或加权平均值中减去的数。 通常情况下,这是正值,但也可能为零或负值。在使用平均和高斯两种算法情况下,通过计算每个像素周围blockSize x blockSize大小像素块的加权均值并减去常量C即可得到自适应阈值。如果使用平均的方法,则所有像素周围的权值相同;如果使用高斯的方法,则每个像素周围像素的权值则根据其到中心点的距离通过高斯方程得到。"""def custom_threshold(image):        #自定义阈值    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)    h, w = gray.shape[:2]    m = np.reshape(gray, [1, w*h])  #降维    mean = m.sum() / (w*h)    #求均值   # print("mean : ", mean)    ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)#利用均值进行图像二值化    cv.imshow("custom_threshold_binary", binary)src = cv.imread("F:/images/text1.png")cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)cv.imshow("input image", src)threshold_demo(src)local_threshold(src)custom_threshold(src)cv.waitKey(0)cv.destroyAllWindows()

运行结果:

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
3,超大图像二值化
对于超大图像,一般要先分块然后再局部二值化(方便显示和进一步后处理):
源代码:

import cv2 as cvimport numpy as npdef big_image_binary(image):    print(image.shape)#查看图像大小    cw = 256          #定义块的大小    ch = 256    h, w = image.shape[:2]    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)    for row in range(0, h, ch):        for col in range(0, w, cw):            roi = gray[row:row+ch, col:cw+col]            #dst = cv.adaptiveThreshold(roi, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY ,127,20)噪声比较多时采用自适应方法比较好            print(np.std(roi), np.mean(roi))            dev = np.std(roi)#针对空白图像,不处理,可以提高效率或者去噪            if dev < 15:                gray[row:row + ch, col:cw + col] = 255            else:                ret, dst = cv.threshold(roi, 0, 255,  | cv.THRESH_OTSU)                gray[row:row + ch, col:cw + col] = dst    cv.imwrite("D:/vcprojects/result_binary.png", gray)src = cv.imread("F:/images/red_text.png")#cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)#cv.imshow("input image", src)big_image_binary(src)cv.waitKey(0)cv.destroyAllWindows()

转载地址:http://rxhwi.baihongyu.com/

你可能感兴趣的文章
点击出现对应界面(第二个界面可以选择显示内容)------Sestid
查看>>
Js实现炫酷仿抖罗盘时钟------Sestid
查看>>
vivo官网鼠标触碰图片拉长------Sestid
查看>>
canvas画布实现的集中效果
查看>>
Js实现点击置顶效果(带动画)
查看>>
Js实现input全选、全不选、反选功能------Sestid
查看>>
纯css实现好看的背景------Sestid
查看>>
为什么我的CSDN上都是开关灯??????Js实现开灯关灯特效
查看>>
Js实现生成自定义输入行列宽高表格------Sestid
查看>>
Js实现购物车加减,价格计算等功能
查看>>
Js自定义快捷键并实现上下左右移动
查看>>
面试看这里!!!2020年前端面试知识点(持续更新)
查看>>
纯CSS实现轮播图------Sestid
查看>>
CSS实现自动播放相册------Sestid
查看>>
JavaScript四种基础的排序方法
查看>>
这里有美女!!!!抖音上很火的3D立体动态相册的实现(纯CSS)
查看>>
一张图让您看懂git,看不懂我也没办法了。。。。。。。。
查看>>
Es6字符串和数组的新方法---自己在控制台都可以看到
查看>>
喜欢NBA的朋友快来这里看第一阶段的全明星投票结果!!!(更新到第二阶段、第三阶段)
查看>>
TCP的三次握手与四次挥手看完这篇文章您要是不理解,那我也没什么办法了!!!
查看>>