【问题标题】:How can I select ROI in a separate image in opencv-python?如何在 opencv-python 的单独图像中选择 ROI?
【发布时间】:2019-03-15 18:15:01
【问题描述】:

我正在使用 python 2.7.13 和 opencv 3.4.0。 我有一个带有 2 个绿点的视频流。我正在使用颜色检测来跟踪它们。我需要在两个单独的图像中选择两个 ROI(感兴趣区域),每个都包含一个点以进行进一步处理。 我编写了一个程序来检测它们并创建 ROI,但问题是它只选择一个区域,而有两个点。 此外,它给了我错误: “第 47 行,在 cv2.imshow ("area1",area1) NameError: name 'area1' is not defined"

但是如果我用 img=cv2.imread("image.jpg") 替换 img=frame.array 行,那么它可以工作,但只能用图片。 Here how program works now

import cv2
import numpy as np
from picamera.array import PiRGBArray
from picamera import PiCamera
import time
import sys

lowerBound=np.array([33,80,40])
upperBound=np.array([102,255,255]) #ranges for green color

camera = PiCamera()
camera.rotation = 180
camera.resolution = (320, 240)
camera.framerate = 30
font=cv2.FONT_HERSHEY_SIMPLEX

rawCapture = PiRGBArray(camera, size=(320, 240))

time.sleep(0.1)
kernelOpen=np.ones((5,5))
kernelClose=np.ones((20,20))

for frame in camera.capture_continuous(rawCapture, format="bgr",         use_video_port=True): # capture frames from the camera
    img = frame.array #works only if I change this with img =cv2.imread("image.jpg")
    imgHSV= cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    mask=cv2.inRange(imgHSV,lowerBound,upperBound)

    maskOpen=cv2.morphologyEx(mask,cv2.MORPH_OPEN,kernelOpen)
    maskClose=cv2.morphologyEx(maskOpen,cv2.MORPH_CLOSE,kernelClose) #apply morphology for greater accuracy
    maskFinal=maskClose
    _, conts, _=cv2.findContours(maskFinal.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)

    for i in range(len(conts)):
        x,y,w,h=cv2.boundingRect(conts[i])
        area1=img[y:y+h, x:x+w] #selecting my ROI
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255), 2)
    cv2.imshow("maskClose",maskClose)
    cv2.imshow("maskOpen",maskOpen)
    cv2.imshow("mask",mask)
    cv2.imshow("cam",img)
    cv2.imshow ("area1",area1) #Showing my ROI

    key = cv2.waitKey(1) & 0xFF
    rawCapture.truncate(0)
    if key == ord("q"):
            break

【问题讨论】:

    标签: python opencv object-detection roi


    【解决方案1】:

    在 for 循环中,您不断设置/覆盖area1,因此输出将始终只有一张图像。您可以通过将 imshow() 移到 for 循环中轻松解决此问题。

    在代码顶部添加:
    prevNrOfContours = 0

    使用以下代码更改帧循环:

        # create a window for each roi
        nrOfContours = len(conts)
        for i in range(nrOfContours):
            x,y,w,h=cv2.boundingRect(conts[i])
            area=img[y:y+h, x:x+w] #selecting my ROI
            cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255), 2)
            cv2.imshow("area" + str(i), area)
    
        # if there are more open windows then roi's
        # then close the windows that will not be refreshed
        if prevNrOfContours > nrOfContours:
            for i in range(nrOfContours, prevNrOfContours):
                cv2.destroyWindow("area" + str(i))
    
        # store the number of roi's in this frame, so it can 
        # be used in the next frame
        prevNrOfContours = nrOfContours
    

    编辑:扩展代码以删除不必要的打开窗口

    Edit2:只选择 2 个最大的轮廓:

        # instantiate list
        contour_list = []
    
        for cnt in contours:
                # get contour size
                area = cv2.contourArea(cnt)
                # add tuple of the contour and its size to the list
                contour_list.append((cnt, area))
    
        # sort list on size
        sorted_list = sorted(contour_list, key=lambda x: x[1])
        # create a window for the 2 largest contours
        for i in range(-2,0):
                x,y,w,h=cv2.boundingRect(sorted_list[i][0])
                roi=img[y:y+h, x:x+w] #selecting my ROI
                cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255), 2)
                cv2.imshow("area" + str(i), roi)
    

    【讨论】:

    • 谢谢你,你帮了我很多!它工作正常,但如果你放置一个对象出现在框架中然后消失,那么就会有一个窗口显示这个对象的最后一个图像。如何自动销毁此类窗口? Here's how it looks like
    • 您可以使用函数 cv2.destroyWindow(window_name) (documentation)。我已修改答案以包含此内容。
    • 再次感谢您,我扩展了我的程序,所以现在它计算每个 ROI 中的像素数:for i in range(len(conts)): x,y,w,h=cv2.boundingRect(conts[i]) area=img[y:y+h, x:x+w] pixNum = cv2.inRange(area,lowerBound,upperBound ) no_black = cv2.countNonZero(pixNum) cv2.imshow("area" + str(i), area) cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255), 2) print (no_black)
    • 但是由于相机上的眩光,我不断得到一些错误的 ROI,它们会作为窗口弹出并严重加载系统。如何只获得两个像素数最大的 ROI?我还希望程序仅显示具有这 2 个 ROI 的窗口。
    • 我用可能的实现更新了答案
    猜你喜欢
    • 1970-01-01
    • 2016-08-29
    • 2016-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多