OpenCV+python:图像二值化

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 cv
import numpy as np


def 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]) -> dst

src参数表示输入图像(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 cv
import numpy as np


def 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()

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值