opencv进阶学习9:图像阈值大全,图像二值化,超大图像二值化

基础版笔记链接:
python3+opencv学习笔记汇总目录(适合基础入门学习)
进阶版笔记目录链接:
python+opencv进阶版学习笔记目录(适合有一定基础)

基础版二值化讲解
opencv学习笔记10:阈值分割

图像二值化原理

二值化方法:全局阈值,局部阈值
具体原理见上面链接

图像二值化实现

1.全局阈值
通常情况,我们一般不知道设定怎样的阈值thresh才能得到比较好的二值化效果,只能去试。如对于一幅双峰图像(理解为图像直方图中存在两个峰),我们指定的阈值应尽量在两个峰之间的峰谷。这时,就可以用第四个参数THRESH_OTSU,它对一幅双峰图像自动根据其直方图计算出合适的阈值(对于非双峰图,这种方法得到的结果可能不理想)。

对于双峰图,我们需要多传入一个参数cv2.THRESH_OTSU,并且把阈值thresh设为0,设置为其他数也默认为0,算法会找到最优阈值,并作为第一个返回值ret返回。

cv2.THRESH_BINARY:二进制阈值。把亮的处理成白色,暗的处理成黑色

cv2.THRESH_BINARY_INV:反二进制阈值。把亮的处理成黑色,暗的处理成白色
cv2.THRESH_TRUNC:截断阈值。亮的不能太亮,有上限,暗的不变
cv2.THRESH_TOZERO_INV:threshold 反阈值化为0,把比较亮的部分处理成0成黑色,小于等于阈值的像素点不变
cv2.THRESH_TOZERO:threshold 阈值化为0,比较亮的部分不变,比较暗的部分处理成黑色为0

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("binary", binary)

print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("duoren.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
threshold_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

图像直方图

该图没有明显两个波峰,将就用

结果

二进制阈值

修改cv.THRESH_BINARY为其他参数。结果如下

cv2.THRESH_BINARY_INV:反二进制阈值

cv2.THRESH_TRUNC:截断阈值

cv2.THRESH_TOZERO_INV: 反阈值化为0

cv2.THRESH_TOZERO:阈值化为0

2.局部阈值 自适应阈值
cv2.adaptiveThreshold()

ADAPTIVE_THRESH_MEAN_C :把图像分成一个个小的区域,每个区域做阈值处理,每个区域阈值为这个区域的均值减去常量c,大于阈值取白色,小于取黑色。整个图像有很多阈值。

ADAPTIVE_THRESH_GAUSSIAN_C:把图像分成一个个小的区域,阈值是每个区域均值的权重和(均值分布为高斯分布,越接近中心均值权重越高)再减去常量c,整个图像只有一个阈值
blocksize:区域大小,必须是奇数。
C: 二值化时,如何一个像素点减去均值大于C,才把这个点设为白色,能减弱噪声影响。等于说阈值=均值-C

在这里插入图片描述

import cv2 as cv
import numpy as np


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("binary", binary)
print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("duoren.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
local_threshold(src)
cv.waitKey(0)
cv.destroyAllWindows()

换一张经典图
自适应阈值结果

全局阈值结果

首先还是自适应阈值吧。

3.自定义阈值
自己实现一个二值化处理

import cv2 as cv
import numpy as np

def custom_threshold(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)#转换为灰度图
    h, w = gray.shape[:2]#高宽
    m = np.reshape(gray, [1, w*h])#将图像转换为1维数组,1行多列
    mean = m.sum() / (w*h)#求均值,把均值作为阈值
    print("mean : ", mean)
    ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)
    cv.imshow("binary", binary)

print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("duoren.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
custom_threshold(src)
cv.waitKey(0)
cv.destroyAllWindows()

超大图像二值化

方法:图像分块,再分别阈值
图超大时,由于光照不能很好分布全图,所以有很多噪声。

import cv2 as cv
import numpy as np

def big_image_binary(image):
    print(image.shape)#(1200, 1920, 3)
    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]#小块区域
            #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_BINARY | cv.THRESH_OTSU)#cv.THRESH_OTSU自动寻找阈值
                #自适应阈值
                #dst = cv.adaptiveThreshold(roi, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)
                gray[row:row + ch, col:cw + col] = dst#在原图上替换小块二值化结果
    #cv.imwrite("result_binary.png", gray)
    cv.imshow('result_binary',gray)
print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("limi.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
big_image_binary(src)
cv.waitKey(0)
cv.destroyAllWindows()

说明
下面代码是去除图像空白小块区域噪声。如果一个小块没有其他东西,那么它的方差就很小,去除一些小黑点(去噪)

if dev < 15:
                gray[row:row + ch, col:cw + col] = 255#去除空白区域的噪点

电气专业的计算机萌新,写博文不容易。如果你觉得本文对你有用,请点个赞支持下。谢谢。

猜你喜欢

转载自blog.csdn.net/kobeyu652453/article/details/107348229