
目标是从面对这种简单环境用opencv画出中线,下面是过程实现
这种环境看似简单,但是用灰度处理二值化的效果奇差,最后选择用HSV进行分割。
先导入包:
import cv2 import cv2 as cv import numpy as np
然后把图片用cvtColor转化成HSV格式
img=cv.imread("1.png")
img=cv.cvtColor(img,cv.COLOR_BGR2HSV)
HSV模型中颜色的参数分别是:色调(H),饱和度(S),明度(V) 色调H用角度度量,取值范围为0~360,从红色开始按逆时针方向计算,红色为0,绿色为120,蓝色为240,他们的补色是: 黄色为60,青色为180,紫色为300 如果直接使用opencv中cvtColor函数,并设置参数为CV_BGR2HSV,那么所得的HSV范围分别是【0,180】【0,255】【0,255】
lower=np.array([0,0,137]) upper=np.array([120,255,255]) mask = cv2.inRange(img,lowerb=lower,upperb=upper)
mask = inRange(hsv,lower_red,upper_red) hsv:原图 lower_red指的是图像中低于这个lower_red的值,图像值变为0 upper_red指的是图像中高于这个upper_red的值,图像值变为0阈值的选择
阈值的选择比较烦人,上面的数值是匹配第一张图片分割的。下面提供一个可视化工具,帮助你找到合适的阈值。
import cv2
import numpy as np
# 滑动条的回调函数,获取滑动条位置处的值
def empty(a):
h_min = cv2.getTrackbarPos("Hue Min", "TrackBars")
h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
print(h_min, h_max, s_min, s_max, v_min, v_max)
return h_min, h_max, s_min, s_max, v_min, v_max
path = '1.png'
# 创建一个窗口,放置6个滑动条
cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars", 640, 240)
cv2.createTrackbar("Hue Min", "TrackBars", 0, 120, empty)
cv2.createTrackbar("Hue Max", "TrackBars", 19, 120, empty)
cv2.createTrackbar("Sat Min", "TrackBars", 110, 255, empty)
cv2.createTrackbar("Sat Max", "TrackBars", 240, 255, empty)
cv2.createTrackbar("Val Min", "TrackBars", 153, 255, empty)
cv2.createTrackbar("Val Max", "TrackBars", 255, 255, empty)
while True:
img = cv2.imread(path)
imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 调用回调函数,获取滑动条的值
h_min, h_max, s_min, s_max, v_min, v_max = empty(0)
lower = np.array([h_min, s_min, v_min])
upper = np.array([h_max, s_max, v_max])
# 获得指定颜色范围内的掩码
mask = cv2.inRange(imgHSV, lower, upper)
# 对原图图像进行按位与的操作,掩码区域保留
imgResult = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow("Mask", mask)
cv2.imshow("Result", imgResult)
cv2.waitKey(1)
边界轮廓线拟合 :
contours_,h_ = cv.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) mask = cv2.cvtColor(mask,cv2.COLOR_GRAY2BGR) cv2.drawContours(mask,contours_,-1,(0,255,0),3)
这里拟合出边界轮廓线并且直接画出来,线的厚度可以在drawContours的最后一个参数3的地方修改。这里contours_的数据类型如下,如果有相关操作注意:
最后展示图片
cv2.imshow("result",mask)
cv2.waitKey(0)
完整代码如下:
import cv2
import cv2 as cv
import numpy as np
img=cv.imread("1.png")
img=cv.cvtColor(img,cv.COLOR_BGR2HSV)
lower=np.array([0,0,137])
upper=np.array([120,255,255])
mask = cv2.inRange(img,lowerb=lower,upperb=upper)
contours_,h_ = cv.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
mask = cv2.cvtColor(mask,cv2.COLOR_GRAY2BGR)
cv2.drawContours(mask,contours_,-1,(0,255,0),3)
cv2.imshow("result",mask)
cv2.waitKey(0)