opencv 查找具有特定宽度和高度的矩形

yrwegjxp  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(112)

我在找我选的尺寸的长方形。在代码中使用框宽和框高,但我发现各种矩形大小。
我有我的测试模式图像。要看到它,当你运行该程序,首先有两个显示器,第二次运行该程序,并移动弹出窗口到显示器的程序是不显示在弹出窗口。
我的程序不能检测到用线分割的矩形,并且有随机的字母和数字接触它。
这是我在测试模式中的第一个问题,这是顶部的图片。
第二个问题是测试图片中的底部图像,即当我调整canny和approxPolyDP数值以允许更多结果时,我在一个图像中得到太多结果。但我只是想找到我想要的大小的矩形。
下面是我代码和测试图片:
test picture
要使用测试图片,请运行程序并通过显示桌面视频的窗口对测试图片进行视频。
下面是我的代码,在Python 3中:

import numpy as np
import cv2
from mss import mss
from PIL import Image
import imutils

sct = mss()
BOX_WIDTH = 235
BOX_HEIGHT = 10

while 1:
    w, h = 240, 640
    monitor = {'top': 100, 'left': 900, 'width': w, 'height': h}

    img = Image.frombytes('RGB', (w, h), sct.grab(monitor).rgb)

    image_data = np.asarray(img)

    # Convert the image to grayscale

    gray = cv2.cvtColor(image_data, cv2.COLOR_BGR2GRAY)

    # Perform Canny edge detection

    edges = cv2.Canny(gray, 600900, 150) # i don't know what these values should be? so i used 900, 150 which makes less results

    # Find contours in the edges image

    hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

    contours = imutils.grab_contours(hierarchy)

    # Iterate over each contour

    for contour in contours:

        # Approximate the contour to a polygon

        polygon = cv2.approxPolyDP(contour, 0.01004 * cv2.arcLength(contour, True), True)  # detects if its a square or rectangle

        # Check if the polygon has 4 sides

        if len(polygon) <= 11:
            # Draw the rectangle on the image

            x, y, w, h = cv2.boundingRect(contour)  # changed polygon to contour

            ratio = float(w) / h
            length = cv2.arcLength(contour, True)
            half_width = BOX_WIDTH // 2
            lift_height = BOX_HEIGHT // 6

            if (length <= 950) and (length >= 100):
                if not ((ratio >= 0.99) and (ratio <= 1.0)):
                    cv2.rectangle(image_data, (x, y), (x + half_width, y + BOX_HEIGHT - lift_height), (0, 0, 255), 2)  # draws green box around rectangle
                else:
                    cv2.rectangle(image_data, (x, y), (x + half_width, y + BOX_HEIGHT - lift_height), (0, 0, 255), 2)  # draws green box around square

        # Show the result

    cv2.imshow('test', image_data)
    if cv2.waitKey(25) & 0xFF == ord('q'):
        cv2.destroyAllWindows()
        break

字符串
为了解决我的第一个问题,我试着在列表中名为“4”的行中查看数字4。轮廓近似”,这里是文档的链接:
https://docs.opencv.org/4.x/dd/d49/tutorial_py_contour_features.html
我尝试了一些测试代码,它没有修复它。我已经失去了测试代码。
对于我的第二个问题,我已经尝试调整我的代码中的值。canny、approxPolyDP、len(多边形)。
我修复了我的问题,我把好的代码放在第一篇文章中,编辑我发现了如何发布答案,所以我撤销编辑,并把旧的坏代码再次放在这篇文章中。现在我去做回答回答。

deyfvvtc

deyfvvtc1#

如果你使用的是obs studio版本29. 1. 3,截至今天几天前我读了opencv更新说明,它说opencv可以运行obs studio虚拟相机!
你可以使用(源,显示捕捉),然后(启动虚拟相机),这样你就可以得到桌面视频,并有机会获得的东西videocapture提供太多!
下面是我使用obs studio捕获桌面屏幕时使用的代码:

# for desktop capture, find the rectangle of a specific width and height
#
# running the program pops up a window to watch the video.
# the program video window shows the first monitor,
# but watch the program video window on second extended monitor 

import cv2
import imutils

# Path to video file
cap = cv2.VideoCapture(
    1,
    apiPreference=cv2.CAP_ANY,
    params=[cv2.CAP_PROP_FRAME_WIDTH, 1280, cv2.CAP_PROP_FRAME_HEIGHT, 720],
)  # I made cap = 1280, 720 resolution to speed the program up on my computer. I have a rtx 3060, obs studio at 60 fps

# Used as counter variable
count = 1

# checks whether frames were extracted
success = 1

# the size of the red box that's around the found rectangle
BOX_WIDTH = 170
BOX_HEIGHT = 26

while success:

    # function extract frames
    success, image = cap.read()

    if count <= 1:
        # Saves the frames with frame-count
        cv2.imwrite("frame_%d.jpg" % count, image, [int(cv2.IMWRITE_JPEG_QUALITY), 100])  # jpg 100% quality

        count += 1

    if count == 2:
        count = 1
        frame = cv2.imread('frame_1.jpg')

        # Perform Canny edge detection

        edges = cv2.Canny(frame, 100, 200)

        # Find contours in the edges image

        hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

        contours = imutils.grab_contours(hierarchy)

        # Iterate over each contour

        for contour in contours:

            # Approximate the contour to a polygon, detects if it's a square or rectangle

            # increase "dial" until you see the box around the rectangle your targeting

            dial = 0.014  # if you change the resolution then this will probably have to be recalibrated

            polygon = cv2.approxPolyDP(contour, dial * cv2.arcLength(contour, True), True)

            # Check if the polygon has 4 sides

            if len(polygon) == 4:
                # Draw the rectangle on the image

                contour_x, contour_y, contour_width, contour_height = cv2.boundingRect(contour)

                ratio = float(contour_width) / contour_height
                half_width = BOX_WIDTH // 2
                lift_height = BOX_HEIGHT // 6

                # I can set the size of the rectangles I find with this line
                # comment out the below if line when you find rectangle with the "dial" variable above
                # (set the below if condition contour_width, contour_height,
                # until you see the box around your rectangle you found with "dial")
                if (contour_width == 59) and (contour_height == 20):
                    # draws green box around rectangle
                    # in (contour_x - 4, contour_y - 4), the 4 is to move the drawn green box over the picture
                    cv2.rectangle(frame, (contour_x - 4, contour_y - 4),
                                  (contour_x + half_width, contour_y + BOX_HEIGHT - lift_height), (0, 255, 0), 2)

            # Show the result

        cv2.imshow('test', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

字符串

n7taea2i

n7taea2i2#

下面的代码与前面的代码不同,因为这段代码查找颜色,并且我将颜色设置为我正在搜索的矩形的颜色。
我包括了一个滑块,这样你就可以改变你搜索的颜色,当你找到它时,程序会把一个红色的矩形放在它找到的东西上。

# for desktop capture, find the rectangle of a specific width and height
#
# running the program pops up a window to watch the video.
# the program video window shows the first monitor,
# but watch the program video window on second extended monitor

import cv2
import numpy as np  # used for finding the color of the rectangle

# start of section for the "to_slide_Color()" function

def fun(x):
    pass

# Window for trackbar
cv2.namedWindow("Detection",cv2.WINDOW_NORMAL)
cv2.resizeWindow('Detection', 500, 500)

cv2.createTrackbar("L_hue", "Detection", 24, 255, fun)
cv2.createTrackbar("L_sat", "Detection", 134, 255, fun)
cv2.createTrackbar("L_val", "Detection", 238, 255, fun)

cv2.createTrackbar("up_hue", "Detection", 120, 180, fun)
cv2.createTrackbar("up_sat", "Detection", 187, 255, fun)
cv2.createTrackbar("up_val", "Detection", 255, 255, fun)

def to_slide_Color():
    # Get positions of trackbars
    L_hue = cv2.getTrackbarPos("L_hue", "Detection")
    L_sat = cv2.getTrackbarPos("L_sat", "Detection")
    L_val = cv2.getTrackbarPos("L_val", "Detection")

    up_hue = cv2.getTrackbarPos("up_hue", "Detection")
    up_sat = cv2.getTrackbarPos("up_sat", "Detection")
    up_val = cv2.getTrackbarPos("up_val", "Detection")

    return L_hue, L_sat, L_val, \
        up_hue, up_sat, up_val

# end of section for the "to_slide_Color()" function

# start  of section for opening the video and creating counter variable

# Path to video file
cap = cv2.VideoCapture(
    1,
    apiPreference=cv2.CAP_ANY,
    params=[cv2.CAP_PROP_FRAME_WIDTH, 1280, cv2.CAP_PROP_FRAME_HEIGHT, 720],
)  # I made cap = 1280, 720 resolution to speed the program up on my computer. I have a rtx 3060, obs studio at 60 fps

# Used as counter variable, it's not specific to either the finding the rectangle shape or the rectangle color
count = 1

# end  of section for opening the video and creating counter variable

while True:
    (lower_hue, lower_saturation, lower_value,
     upper_hue, upper_saturation, upper_value) = to_slide_Color()
    # this is the start of finding the color of the rectangle

    # function extract frames
    success, image = cap.read()

    if count <= 1:
        # Saves the frames with frame-count
        cv2.imwrite("frame_%d.jpg" % count, image, [int(cv2.IMWRITE_JPEG_QUALITY), 100])  # jpg 100% quality

        count += 1

    if count == 2:
        count = 1
        frame = cv2.imread('frame_1.jpg')

        # Convert BGR to HSV
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

        # define range of blue color in HSV
        lower_blue = np.array([lower_hue, lower_saturation, lower_value])
        upper_blue = np.array([upper_hue, upper_saturation, upper_value])

        # Threshold the HSV image to get only blue colors
        blue_mask = cv2.inRange(hsv, lower_blue, upper_blue)

        blue_contours = cv2.findContours(blue_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]

        red = 255
        red_line_thickness = 1

        if len(blue_contours) > 0:
            blue_area = max(blue_contours, key=cv2.contourArea)
            (x, y, width, height) = cv2.boundingRect(blue_area)
            cv2.rectangle(frame, (x - 3, y - 2), (x + width, y + height), (0, 0, red), red_line_thickness)

        cv2.imshow('frame', frame)
        cv2.imshow('blue_mask', blue_mask)

        # this is the end of finding the color of the rectangle

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# Release the video
cap.release()

# Destroy the windows
cv2.destroyAllWindows()

字符串

相关问题