一. 提取颜色
⭐运用的知识:
视频处理、滚动条、HSV色彩空间、标记指定颜色
通过滚动条调整HSV图像三个通道的取值范围,提取画笔的颜色。
import cv2
import numpy as np
frameWidth = 640
frameHeight = 480
cap = cv2.VideoCapture(0)
cap.set(3, frameWidth)
cap.set(4, frameHeight)
def empty(a):
pass
cv2.namedWindow("HSV")
cv2.resizeWindow("HSV", 640, 240)
cv2.createTrackbar("HUE Min", "HSV", 0, 179, empty)
cv2.createTrackbar("HUE Max", "HSV", 179, 179, empty)
cv2.createTrackbar("SAT Min", "HSV", 0, 255, empty)
cv2.createTrackbar("SAT Max", "HSV", 255, 255, empty)
cv2.createTrackbar("VALUE Min", "HSV", 0, 255, empty)
cv2.createTrackbar("VALUE Max", "HSV", 255, 255, empty)
while True:
success, img = cap.read()
imgHsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h_min = cv2.getTrackbarPos("HUE Min", "HSV")
h_max = cv2.getTrackbarPos("HUE Max", "HSV")
s_min = cv2.getTrackbarPos("SAT Min", "HSV")
s_max = cv2.getTrackbarPos("SAT Max", "HSV")
v_min = cv2.getTrackbarPos("VALUE Min", "HSV")
v_max = cv2.getTrackbarPos("VALUE Max", "HSV")
print(h_min)
lower = np.array([h_min, s_min, v_min])
upper = np.array([h_max, s_max, v_max])
mask = cv2.inRange(imgHsv, lower, upper)
result = cv2.bitwise_and(img, img, mask=mask)
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
hStack = np.hstack([img, mask, result])
cv2.imshow('Horizontal Stacking', hStack)
c = cv2.waitKey(25)
if c==27:
break
cap.release()
cv2.destroyAllWindows()
二. 虚拟画笔实现
⭐用到的知识(除了上一步用到的知识):
逼近多边形、图像轮廓、图形绘制
在myColors列表中写入上一步中得到的HSV的范围(可以写任意多个),在myColorValues列表中写入画笔颜色对应的RGB(列表长度与myColors一致)。
import cv2
import numpy as np
frameWidth = 640
frameHeight = 480
cap = cv2.VideoCapture(0)
cap.set(3, frameWidth)
cap.set(4, frameHeight)
cap.set(10,150)
myColors = [[76,71,191,93,255,255]] #H_low,S_low,V_low,H_high,S_high,V_high,可以放任意多个颜色
myColorValues = [[51,153,255]] ## 绘制圆圈的颜色
myPoints = [] ## [x , y , colorId ]
# 查抄轮廓
def findColor(img,myColors,myColorValues):
imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
count = 0
newPoints=[]
for color in myColors:
lower = np.array(color[0:3])
upper = np.array(color[3:6])
mask = cv2.inRange(imgHSV,lower,upper)
x,y=getContours(mask)
cv2.circle(imgResult,(x,y),15,myColorValues[count],cv2.FILLED)
if x!=0 and y!=0:
newPoints.append([x,y,count])
count +=1
cv2.imshow(str(color[0]),mask)
return newPoints
#获取笔尖坐标
def getContours(img):
image, contours, hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
x,y,w,h = 0,0,0,0
for cnt in contours:
area = cv2.contourArea(cnt)
if area>500:
#cv2.drawContours(imgResult, cnt, -1, (255, 0, 0), 3)
peri = cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,0.02*peri,True)
x, y, w, h = cv2.boundingRect(approx)
return x+w//2,y
#绘制轮廓
def drawOnCanvas(myPoints,myColorValues):
for point in myPoints:
cv2.circle(imgResult, (point[0], point[1]), 10, myColorValues[point[2]], cv2.FILLED)
while True:
success, img = cap.read()
imgResult = img.copy()
newPoints = findColor(img, myColors,myColorValues)
if len(newPoints)!=0:
for newP in newPoints:
myPoints.append(newP)
if len(myPoints)!=0:
drawOnCanvas(myPoints,myColorValues)
cv2.imshow("Result", imgResult)
c = cv2.waitKey(25)
if c==32: #空格清屏
myPoints = []
if c==27: #esc退出
break
cap.release()
cv2.destroyAllWindows()