threshold函数定义如下:
def threshold(src, thresh, maxval, type, dst=None):
第一个参数:src。
input array (multiple-channel, 8-bit or 32-bit floating point). 即为输入图像,但需转化为8或32位单通道,即灰度图像。
第二个参数:thresh。
threshold value.自己设定的阈值,这个阈值的对后面的操作有影响,而它的作用又需要第四个参数来指定。
第三个参数:maxval。
maximum value to use with the #THRESH_BINARY and #THRESH_BINARY_INV thresholding types.设定的最大阈值,当type设定为特定的两个值时,才会起作用。
第四个参数:type。
thresholding type (see #ThresholdTypes).这个类型影响着两个阈值。可以取以下几个值:
THRESH_BINARY = 0
THRESH_BINARY_INV = 1
THRESH_MASK = 7
THRESH_OTSU = 8
THRESH_TOZERO = 3
THRESH_TOZERO_INV = 4
THRESH_TRIANGLE = 16
THRESH_TRUNC = 2
由于我也是初学OpenCV,目前只用到了前两个,所以只对他们做介绍。
(1)当type设定为cv2.THRESH_BINARY时,src中像素值大于thresh的像素点会设置为maxval,小于thresh的设置为0。
(2)当type设为cv2.THRESH_BINARY_INV时,src中像素值大于thresh的设置为0,而小于thresh的则设置为maxval。和第一个参数相反。
我这里做的是轮廓检测(用矩形和圆形包围目标的边框),可以明显看出阈值参数设置后的效果。我个人理解为:如果图片背景是深色,则设置为THRESH_BINARY;若图片背景是浅色,则type设置为THRESH_BINARY_INV。
1. 深色背景图一是设置为THRESH_BINARY的效果,图二是设置为THRESH_BINARY_INV的效果。
可以看出图二根本没有识别出目标,而是识别了图片边框,这显然不是我们要的结果。
图一是设置为THRESH_BINARY的效果,图二是设置为THRESH_BINARY_INV的效果。
当背景为白色时,这里的参数应设置为THRESH_BINARY_INV。
我将部分代码粘出:
import cv2
import numpy as np
img = cv2.pyrDown(cv2.imread("images/fruit.jpg", cv2.IMREAD_UNCHANGED))
ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY_INV)
image, contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for con in contours:
# 画出简单的边界框,(x,y)坐标,矩形高,宽
x, y, w, h = cv2.boundingRect(con)
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 计算出包围目标的最小矩形区域
rect = cv2.minAreaRect(con)
box = cv2.boxPoints(rect)
# 将像素值转为int类型
box = np.int0(box)
cv2.drawContours(img, [box], 0, (0, 0, 255), 3)
# 画出最小闭圆
(x, y), radius = cv2.minEnclosingCircle(c) # 圆心坐标和半径
center = (int(x), int(y))
radius = int(radius)
img = cv2.circle(img, center, radius, (0, 255, 0), 2)
cv2.drawContours(img, contours, -1, (255, 0, 0), 1)