Vanilla_2 2021-01-16 22:27 采纳率: 66.7%
浏览 54
已采纳

python机器视觉方向,如何修改代码使程序变得更加流畅?

这是一段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:结构可以吗。

 

  • 写回答

12条回答 默认 最新

  • 无厘头编程 2021-01-18 08:56
    关注

    更新版:

    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()关闭所有图像窗口。
    

     

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(11条)

报告相同问题?

悬赏问题

  • ¥20 java在应用程序里获取不到扬声器设备
  • ¥15 echarts动画效果的问题,请帮我添加一个动画。不要机器人回答。
  • ¥60 许可证msc licensing软件报错显示已有相同版本软件,但是下一步显示无法读取日志目录。
  • ¥15 Attention is all you need 的代码运行
  • ¥15 一个服务器已经有一个系统了如果用usb再装一个系统,原来的系统会被覆盖掉吗
  • ¥15 使用esm_msa1_t12_100M_UR50S蛋白质语言模型进行零样本预测时,终端显示出了sequence handled的进度条,但是并不出结果就自动终止回到命令提示行了是怎么回事:
  • ¥15 前置放大电路与功率放大电路相连放大倍数出现问题
  • ¥80 部署运行web自动化项目
  • ¥15 腾讯云如何建立同一个项目中物模型之间的联系
  • ¥30 VMware 云桌面水印如何添加