这是一段python机器视觉方向的代码,使用opencv库进行摄像头图像操作。目的是获取设定颜色(红,绿,蓝,黄)的外包矩形(仅一个矩形,横平竖直的,没必要是最小的),并且输出这个外包举行的中心在画布上面的横纵坐标值。
from __future__ import division
import cv2
import numpy as np
import time
# HSV色彩空间,Hue:色调(颜色);Sat:饱和度(一种颜色混合白光的数量);Val:亮度(明暗程度)
#创建回调函数
def nothing(*arg):
pass
FRAME_WIDTH = 800
FRAME_HEIGHT = 600
# Initial HSV GUI slider values to load on program start.要在程序启动时加载的初始HSV GUI滑块值。
# icol = [36, 202, 59, 71, 255, 255] # Green
# icol = [18, 0, 196, 36, 255, 255] # Yellow
icol = [89, 0, 0, 125, 255, 255] # Blue
#icol = [0, 100, 80, 10, 255, 255] # Red
# icol = [104, 117, 222, 121, 255, 255] # test
# icol = [0, 0, 0, 255, 255, 255] # New start
cv2.namedWindow('colorTest',cv2.WINDOW_AUTOSIZE)#('窗口标题',默认参数)//窗口大小比例不可改变
#cv2.creatTrackbar()函数的第一个参数时滑动条的名字,第二个参数时滑动条被放置的窗口的名字,
#第三个参数是滑动条默认值,第四个参数时滑动条的最大值,第五个参数时回调函数,每次滑动都会调用回调函数。
# Lower range colour sliders.低量程彩色滑块。
cv2.createTrackbar('lowHue', 'colorTest', icol[0], 255, nothing)
cv2.createTrackbar('lowSat', 'colorTest', icol[1], 255, nothing)
cv2.createTrackbar('lowVal', 'colorTest', icol[2], 255, nothing)
# Higher range colour sliders.更高范围的彩色滑块。
cv2.createTrackbar('highHue', 'colorTest', icol[3], 255, nothing)
cv2.createTrackbar('highSat', 'colorTest', icol[4], 255, nothing)
cv2.createTrackbar('highVal', 'colorTest', icol[5], 255, nothing)
vidCapture = cv2.VideoCapture(0)#打开笔记本的内置摄像头//参数是视频文件路径则打开视频,如cap = cv2.VideoCapture(“../test.avi”)
#cv2.VideoCapture().set(propId, value)设置摄像头
vidCapture.set(cv2.CAP_PROP_FRAME_WIDTH, FRAME_WIDTH)
vidCapture.set(cv2.CAP_PROP_FRAME_HEIGHT, FRAME_HEIGHT)
while(True):
#time.sleep(0.1)
timeCheck = time.time()#检查时间是否为有效时间
#cv2.getTrackbarPos(),共有2个参数,第一个参数是滑动条名字,第二个时所在窗口偶,返回值是滑动条位置。
#Get HSV values from the GUI sliders.从GUI滑块获取HSV值。
lowHue = cv2.getTrackbarPos('lowHue', 'colorTest')
lowSat = cv2.getTrackbarPos('lowSat', 'colorTest')
lowVal = cv2.getTrackbarPos('lowVal', 'colorTest')
highHue = cv2.getTrackbarPos('highHue', 'colorTest')
highSat = cv2.getTrackbarPos('highSat', 'colorTest')
highVal = cv2.getTrackbarPos('highVal', 'colorTest')
# Get webcam frame.获取网络摄像头帧。
_, frame = vidCapture.read()
# Show the original image.显示原始图像。
cv2.imshow('frame', frame)
# Convert the frame to HSV colour model.将框架转换为HSV彩色模型。
frameHSV = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# HSV values to define a colour range we want to create a mask from.HSV值来定义要从中创建遮罩的颜色范围。
colorLow = np.array([lowHue, lowSat, lowVal])
colorHigh = np.array([highHue, highSat, highVal])
mask = cv2.inRange(frameHSV, colorLow, colorHigh)
#利用cv2.inRange函数设阈值,去除背景部分
#在opencv中查找轮廓时,物体应该是白色而背景应该是黑色
#一个列表,每一项都是一个轮廓, 不会存储轮廓所有的点,只存储能描述轮廓的点
#hierarchy:一个ndarray, 元素数量和轮廓数量一样,
#每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],
#分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数
#contours, hierarchy = cv2.findContours(输入图像,轮廓的检索模式,轮廓的近似方法)
#轮廓的检索模式
#cv2.RETR_EXTERNAL表示只检测外轮廓
#cv2.RETR_LIST检测的轮廓不建立等级关系
#cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。
#如果内孔内还有一个连通物体,这个物体的边界也在顶层
#cv2.RETR_TREE建立一个等级树结构的轮廓
#轮廓的近似办法
#cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,
#即max(abs(x1-x2),abs(y2-y1))==1
#cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours]
biggest_contour = max(contour_sizes, key=lambda x: x[0])[1]
x, y, w, h = cv2.boundingRect(biggest_contour)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
print((x+w)/2,(y+h)/2)
cv2.destroyAllWindows()#调用destroyAllWindows()关闭所有图像窗口。
vidCapture.release()#release()释放摄像头
要求:1、修改代码去掉colorTest界面里面全部的滑条,(用#注释掉对应的代码就行)只显示一个识别出来的图片。
整个代码使用预先设定好的参数进行运行,不需要在程序运行的时候调整数值。
2、这个代码在我的电脑上会出现程序卡死的情况,但是代码仍然可以输出信息,这个信息就是外包矩形的中心横纵坐标的位置,说明底层代码还是可以运行的。看看是哪一段的问题。并且给解决掉,我用的是python3.7.3。
3、当屏幕没有检测到自己设定的颜色的时候,会报错,说一个集合是空的,能不能通过某种方式输出“???”并且重新执行这段代码,而不是程序直接退出了。try:except:结构可以吗。
更新版:
from __future__ import division
import cv2
import numpy as np
# ==================================================================
# global
# HSV 色值:
GREEN = [40, 65, 13, 80, 255, 255] # Green
YELLOW = [20, 103, 80, 40, 255, 255] # Yellow
BLUE = [94, 81, 82, 126, 255, 255] # Blue
RED = [0, 144, 0, 20, 255, 255] # Red
# default value: Blue 蓝色
lowHue = BLUE[0]
lowSat = BLUE[1]
lowVal = BLUE[2]
highHue = BLUE[3]
highSat = BLUE[4]
highVal = BLUE[5]
# 滑动名称
blue_bar = 'Blue'
red_bar = 'Red'
yellow_bar = 'Yellow'
green_bar = 'Green'
# 排列:green, yellow, blue, red
defaultColor = [0, 0, 1, 0] # 蓝色
color = "BLUE" # 现在的颜色
blueColor = (255, 0, 0) # 蓝色
greenColor = (0, 255, 0) # 绿色
redColor = (0, 0, 255) # 红色
# 图像色调和追踪
def frame_mask_contour(image):
frameHSV = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# HSV values to define a colour range we want to create a mask from.
# HSV值来定义要从中创建遮罩的颜色范围。
colorLow = np.array([lowHue, lowSat, lowVal])
colorHigh = np.array([highHue, highSat, highVal])
mask = cv2.inRange(frameHSV, colorLow, colorHigh)
# get contours
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours]
count = len(contour_sizes)
found = False
if count > 0:
for cnt in contours:
area = cv2.contourArea(cnt)
if area > 2000:
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(image, (x, y), (x + w, y + h), greenColor, 2)
found = True
if found:
text = f'Found {color} object'
print(text)
cv2.putText(image, text, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, blueColor, 2)
else:
text = "Not Found!"
print("Not Found! 没有找到!")
cv2.putText(image, text, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, redColor, 2)
return mask, image
# video test 摄像头接通测试
def test(cap, source):
if cap is None or not cap.isOpened():
print('Warning: unable to open video source: ', source)
return False
else:
_, tmp = cap.read()
if tmp is not None:
return True
else:
print("Warning: unable to read video feed.")
return False
# update color 更新颜色
def assignColor(color):
global lowHue, lowSat, lowVal, highHue, highSat, highVal
lowHue = color[0]
lowSat = color[1]
lowVal = color[2]
highHue = color[3]
highSat = color[4]
highVal = color[5]
# 绿色控制
def greenCtrl(val):
global defaultColor, color
color = 'GREEN'
defaultColor = [1, 0, 0, 0]
assignColor(GREEN)
# 黄色控制
def yellowCtrl(val):
global defaultColor, color
color = 'YELLOW'
defaultColor = [0, 1, 0, 0]
assignColor(YELLOW)
# 蓝色控制
def blueCtrl(val):
global defaultColor, color
color = 'BLUE'
defaultColor = [0, 0, 1, 0]
assignColor(BLUE)
# 红色控制
def redCtrl(val):
global defaultColor, color
color = 'RED'
defaultColor = [0, 0, 0, 1]
assignColor(RED)
# 更新滑块
def updateTrackbar():
cv2.setTrackbarPos(green_bar, color_win, defaultColor[0])
cv2.setTrackbarPos(yellow_bar, color_win, defaultColor[1])
cv2.setTrackbarPos(blue_bar, color_win, defaultColor[2])
cv2.setTrackbarPos(red_bar, color_win, defaultColor[3])
# =====================================
# main
# =====================================
FRAME_WIDTH = 800
FRAME_HEIGHT = 600
# =====================================
# Status bar
# =====================================
color_win = 'Choose Color'
cv2.namedWindow(color_win) # ('窗口标题',默认参数)//窗口大小比例不可改变
cv2.resizeWindow(color_win, 500, 310)
cv2.moveWindow(color_win, 857, 520)
cv2.createTrackbar(green_bar, color_win, 0, 1, greenCtrl)
cv2.createTrackbar(yellow_bar, color_win, 0, 1, yellowCtrl)
cv2.createTrackbar(blue_bar, color_win, 0, 1, blueCtrl)
cv2.createTrackbar(red_bar, color_win, 0, 1, redCtrl)
# =====================================
# Camera Len 选择镜头
# =====================================
vidCapture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
videoFeed = test(vidCapture, 0) # camera test 摄像测试
if not videoFeed:
print("No video input! 摄像头没有连接")
exit(1)
# =====================================
# Window 窗口: Frame
# =====================================
vidCapture.set(cv2.CAP_PROP_FRAME_WIDTH, FRAME_WIDTH)
vidCapture.set(cv2.CAP_PROP_FRAME_HEIGHT, FRAME_HEIGHT)
video_win = 'Frame'
cv2.namedWindow(video_win, cv2.WINDOW_AUTOSIZE)
cv2.moveWindow(video_win, 855, 0)
# =====================================
# Window 窗口: Demo
# =====================================
demo_win = 'Demo'
cv2.namedWindow(demo_win)
cv2.moveWindow(demo_win, 205, 0)
# =====================================
# Begin
# =====================================
while vidCapture.isOpened():
updateTrackbar()
# Get webcam frame.获取网络摄像头帧。
_, frame = vidCapture.read()
# Show the original image.显示原始图像。
demo, frame_contour = frame_mask_contour(frame)
cv2.imshow(video_win, frame_contour)
cv2.imshow(demo_win, demo)
key = cv2.waitKey(1)
if key == ord("q") or key == ord("Q"): # q or Q
break
vidCapture.release() # release()释放摄像头
cv2.destroyAllWindows() # 调用destroyAllWindows()关闭所有图像窗口。
哇,一开机就死掉了。
cv2.createTrackbar('lowHue', 'colorTest', icol[0], 255, nothing) 这个 callback 的 nothing() 里面什么都没有,无法输出。
cv2.imshow('frame', frame) 以下到 while...loop 的结尾是独立方程的一部分。请删除,移到外面,由 nothing 召唤。
秒测挺好的,
while vidCapture.isOpened(): time.sleep(1) # timeCheck = time.time() # Get webcam frame.获取网络摄像头帧。 _, frame = vidCapture.read() # Show the original image.显示原始图像。 cv2.imshow('frame', frame) key = cv2.waitKey(1) if key == ord("q") or key == ord("Q"): # q or Q break frame = set_frame_color(frame) # 多余的全部移到这
得到储存的地方是
Traceback (most recent call last):
File "D:/pycode/example/color_pick.py", line 117, in <module>
frame = set_frame_color(frame)
File "D:/pycode/example/color_pick.py", line 50, in set_frame_color
biggest_contour = max(contour_sizes, key=lambda x: x[0])[1]
ValueError: max() arg is an empty sequence
trackbar 独立出来。测高低值。
icol = [89, 0, 0, 125, 255, 255] # Blue
# default value lowHue = icol[0] lowSat = icol[1] lowVal = icol[2] highHue = icol[3] highSat = icol[4] highVal = icol[5] # trackbar name lowHue_bar = 'lowHue' highHue_bar = 'highHue' lowSat_bar = 'lowSat' highSat_bar = 'highSat' lowVal_bar = 'lowVal' highVal_bar = 'highVal'
trackbar callback-- 例如:
# lowHue trackbar def lowHue_tbar(val): global lowHue, highHue if val < highHue: lowHue = val else: print(f'Error: val--{val} > {highHue}') # highHue trackbar def highHue_tbar(val): global lowHue, highHue if val > lowHue: highHue = val else: print(f'Error: val--{val} < {lowHue}')
建立 trackbar:
trackbar_win = 'HSV Setting' cv2.namedWindow(trackbar_win) # ('窗口标题',默认参数)//窗口大小比例不可改变 cv2.resizeWindow(trackbar_win, 500, 350) cv2.moveWindow(trackbar_win, 300, 100) # 低量程彩色滑块。 cv2.createTrackbar(lowHue_bar, trackbar_win, lowHue, 255, lowHue_tbar) cv2.createTrackbar(highHue_bar, trackbar_win, highHue, 255, highHue_tbar)
这样高低不会对冲,下面是更新 trackbars:
while vidCapture.isOpened(): # time.sleep(1) # timeCheck = time.time() updateTrackbar() # Get webcam frame.获取网络摄像头帧。 _, frame = vidCapture.read() # Show the original image.显示原始图像。 cv2.imshow(video_win, frame)
更新方程:
def updateTrackbar(): cv2.setTrackbarPos(lowHue_bar, trackbar_win, lowHue) cv2.setTrackbarPos(highHue_bar, trackbar_win, highHue) cv2.setTrackbarPos(lowSat_bar, trackbar_win, lowSat) cv2.setTrackbarPos(highSat_bar, trackbar_win, highSat) cv2.setTrackbarPos(lowVal_bar, trackbar_win, lowVal) cv2.setTrackbarPos(highVal_bar, trackbar_win, highVal)
Remark contour, 下面测试trackbar, 加多一个窗口:Demo。
video_win = 'Frame' cv2.namedWindow(video_win, cv2.WINDOW_AUTOSIZE) cv2.moveWindow(video_win, 805, 100) demo_win = 'Demo' cv2.namedWindow(demo_win) cv2.resizeWindow(demo_win, DEMO_WIDTH, DEMO_HEIGHT) cv2.moveWindow(demo_win, 805, 425)
下面加:
while vidCapture.isOpened(): # time.sleep(1) # timeCheck = time.time() updateTrackbar() # Get webcam frame.获取网络摄像头帧。 _, frame = vidCapture.read() # Show the original image.显示原始图像。 cv2.imshow(video_win, frame) # Demo image frame_HSV = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) frame_threshold = cv2.inRange(frame_HSV, (lowHue, lowSat, lowVal), (highHue, highSat, highVal)) cv2.imshow(demo_win, frame_threshold) key = cv2.waitKey(1) if key == ord("q") or key == ord("Q"): # q or Q break # updateTrackbar() # frame = set_frame_color(frame)
我把你窗口的值改小了:
FRAME_WIDTH = 400
FRAME_HEIGHT = 300
DEMO_WIDTH = 400
DEMO_HEIGHT = 300
换回 set_frame_color() 看 contour,长方形偏大,这个你自己改罗。
while vidCapture.isOpened():
# time.sleep(1)
# timeCheck = time.time()
updateTrackbar()
# Get webcam frame.获取网络摄像头帧。
_, frame = vidCapture.read()
# Show the original image.显示原始图像。
cv2.imshow(video_win, frame)
# Demo image
frame_threshold = set_frame_color(frame)
cv2.imshow(demo_win, frame_threshold)
key = cv2.waitKey(1)
if key == ord("q") or key == ord("Q"): # q or Q
break
vidCapture.release() # release()释放摄像头
cv2.destroyAllWindows() # 调用destroyAllWindows()关闭所有图像窗口。
你自个的,我帮你搬家了: def set_frame_color(image): frameHSV = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # HSV values to define a colour range we want to create a mask from. # HSV值来定义要从中创建遮罩的颜色范围。 colorLow = np.array([lowHue, lowSat, lowVal]) colorHigh = np.array([highHue, highSat, highVal]) mask = cv2.inRange(frameHSV, colorLow, colorHigh) # get contours contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours] biggest_contour = max(contour_sizes, key=lambda x: x[0])[1] x, y, w, h = cv2.boundingRect(biggest_contour) cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) print((x + w) / 2, (y + h) / 2) return image
能不能给一段完整的代码,不是专门搞代码的,这方面不太懂。
# Camera Len 选择镜头
如果你有第二摄像头的话,应该是 1.
用手机的话请看我的文章:https://blog.csdn.net/fly_bear_unknown/article/details/112265085
测试结果