QQ:3020889729 小蔡
(以上展示代码是后边实例的整合——简单的把彩色/灰度图像放在不同的数组中,然后遍历即可)
在图像处理中,常常对图像进行特征处理,而阈值也是图像的特征属性——每一个像素对应着一定的数据——灰度图像为8位的强度数据,彩色图像为32位的BGR数据。
生活中我们其实在处理问题时经常用到阈值处理——比如:多个裁判评分去掉最低分和最高分,再计算实际数据。比如,一个公司在起步阶段,需要一部分技术人员——只有超过预期能力才会被选择,否则就是被排除掉——当然,我的比喻可能不太对,但是呢,就是想希望这样能让你明白——opencv他也是这样工作的,至于一些特殊的阈值比较方式就是opencv为了解决问题所应用设计的了。
输入参数如下:
def threshold(src, thresh, maxval, type, dst=None): # real signature unknown; restored from __doc__
输出参数:
下面提一下阈值类型,我觉得很有必要——
这些类型都跟实际需要的情况相关——自由选择(一般选择前5种,末尾支持的两种可以作为添加条件,补充阈值操作)。
需要知道的是,前五种除了应用灰度图像外,也满足彩色图像——而最后两种仅仅是二值操作,所以就只适用8位的灰度图像了——即对强度数据进行阈值操作。
以下类型解释——以表达式为准,文字仅仅作为参考和促进理解。
这个阈值类型指——当输入图像大于我们设置的阈值时,就把对应像素数据设置为我们设置的值(maxvalue),否则为图像本身的值。
Python: cv.THRESH_MASK——不支持——这个不多说明,因为我知道的也是不多,后边有机会补正。
Python: cv.THRESH_OTSU——不支持32位的彩色图像, 仅仅支持8位灰度图像
Python: cv.THRESH_TRIANGLE——不支持32位的彩色图像, 仅仅支持8位灰度图像
import cv2 as cv
img = cv.imread('../imag_in_save/images.png')
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 这样可以获得灰度图像
# 也可以用img = cv.imread('../imag_in_save/images.png', 0)直接获得
# 我是为了最后边的样例做灰度变化和彩色变化对比做的准备操作的——即程序保留有彩色图像的数据
ret1, thresh1 = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY) # src(x,y) > 127 => dst(输出)(x,y) = 255
cv.imshow('imag', img)
cv.imshow('imag3', thresh1) # 输出阈值处理的图像
cv.waitKey(0) # 等待按键输入
cv.destroyAllWindows()
import cv2 as cv
if __name__ == "__main__":
img = cv.imread('../imag_in_save/images.png')
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 依次遍历转换——可以直接使用list,但是我为了展示就独立写了
ret1, thresh1 = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY) # 满足阈值设置255(我们设置的最大值)反之为0
ret2, thresh2 = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY_INV) # 满足阈值设置0,反之255
ret3, thresh3 = cv.threshold(img_gray, 127, 255, cv.THRESH_MASK) # 顺便演示一下,具体该用在哪些地方,后边遇到了回来修正
ret4, thresh4 = cv.threshold(img_gray, 127, 255, cv.THRESH_OTSU) # 使用otus算法取最优阈值_只适合灰度图像(文末说明,篇幅)
ret5, thresh5 = cv.threshold(img_gray, 127, 255, cv.THRESH_TOZERO) # 满足保留原数据,否则为0,与设置的最值255无关了
ret6, thresh6 = cv.threshold(img_gray, 127, 255, cv.THRESH_TOZERO_INV) # 与THRESH_TOZERO相反
ret7, thresh7 = cv.threshold(img_gray, 127, 255, cv.THRESH_TRIANGLE) # 使用三角算法取最优阈值_只适合灰度图像(文末说明,篇幅)
ret8, thresh8 = cv.threshold(img_gray, 127, 255, cv.THRESH_TRUNC) # 满足阈值设置255,反之保留原数据
title = ['THRESH_BINARY', 'THRESH_BINARY_INV', 'THRESH_MASK', 'THRESH_OTSU', 'THRESH_TOZERO', 'THRESH_TOZERO_INV',
'THRESH_TRIANGLE', 'THRESH_TRUNC']
img_list = [thresh1, thresh2, thresh3, thresh4, thresh5, thresh6, thresh7, thresh8]
# 字体颜色根据图像本身来传入对应的数据类型——彩色为三元元组
# 灰度图像——传入强度即可
for i in range(0, 8): # 往图片上写文字——即使用的阈值类型
cv.putText(img_list[i], title[i], (25, 60), cv.FONT_HERSHEY_COMPLEX_SMALL, 1, 220, 2, cv.LINE_AA)
i = 0
while True: # 遍历展示
cv.imshow('imag', img_list[i])
k = cv.waitKey(1000) & 0xFF
if k == 27:
break
i += 1
if i == 8:
i = 0
cv.destroyAllWindows()
实现还是和之前的灰度图像的阈值操作一般无二。
import cv2 as cv
if __name__ == "__main__":
img = cv.imread('../imag_in_save/images.png')
ret1, thresh1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY) # 满足阈值设置255(我们设置的最大值)反之为0
cv.imshow('imag', img)
cv.imshow('imag_THRESH_BINARY', thresh1)
cv.waitKey(0)
cv.destroyAllWindows()
import cv2 as cv
if __name__ == "__main__":
img = cv.imread('../imag_in_save/images.png')
ret1, thresh1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY) # 满足阈值设置255(我们设置的最大值)反之为0
ret2, thresh2 = cv.threshold(img, 127, 255, cv.THRESH_BINARY_INV)
ret3, thresh3 = cv.threshold(img, 127, 255, cv.THRESH_MASK) # 顺便演示一下
ret4, thresh4 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO)
ret5, thresh5 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO_INV) # 与THRESH_TOZERO相反
ret6, thresh6 = cv.threshold(img, 127, 255, cv.THRESH_TRUNC)
title = ['THRESH_BINARY', 'THRESH_BINARY_INV', 'THRESH_MASK', 'THRESH_TOZERO', 'THRESH_TOZERO_INV', 'THRESH_TRUNC']
img_list = [thresh1, thresh2, thresh3, thresh4, thresh5, thresh6]
# 字体颜色根据图像本身来传入对应的数据类型——彩色为三元元组
# 灰度图像——传入强度即可
for i in range(0, 6): # 往图片上写文字——即使用的阈值类型
cv.putText(img_list[i], title[i], (25, 60), cv.FONT_HERSHEY_COMPLEX_SMALL, 1, (40, 180, 80), 2, cv.LINE_AA)
i = 0
while True: # 遍历展示
cv.imshow('imag', img_list[i])
k = cv.waitKey(1200) & 0xFF
if k == 27:
break
i += 1
if i == 6:
i = 0
cv.destroyAllWindows()
这次讲解就到这里了——希望能帮助到你哪怕一点。后期有应用,我会补充这一章节的实践操作部分。(前边写的文章我也会慢慢积累,然后进行修改订正的。)