OPENCV:如何在Python中绘制一个旋转的边界盒

发布于 2025-01-25 17:22:09 字数 1298 浏览 2 评论 0原文

我目前正在使用OpenCV-Python进行绘画识别项目。 目前,我能够在相当的情况下检测到大多数绘画,但是边界框是包括很多背景的矩形。 这是因为cv2.boundingRect()函数找到了具有垂直投影(AFAIK)的边界矩形。但是,我想找到最好的边界框,而无需检测到任何背景。

我的代码的主要部分:

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

hue, saturation, value = cv2.split(hsv)
blurred_sat = cv2.GaussianBlur(saturation, (5, 5), 0)
edges = cv2.Canny(blurred_sat, 45, 100)

kernel = np.ones((3, 3), np.uint8)
dilate = cv2.dilate(edges, kernel, iterations=6)
erode = cv2.erode(dilate, kernel, iterations=2)
contours, hierarchy = cv2.findContours(erode, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

contours = sorted(contours, key=cv2.contourArea, reverse=True)[:10]

# cv2.drawContours(frame, contours, -1, (255, 255, 0), 3)
for contour in contours:
    area = cv2.contourArea(contour)
    if area >= 3000:
        x, y, w, h = cv2.boundingRect(contour)
        subImg = frame[y:y+h, x:x+w]
        cv2.rectangle(frame,
                      (x, y), (x + w, y + h),
                      (0, 255, 0),
                      2)

当前输出image(视频) 所需的输出图像,带有所需的边界框,红色

I am currently doing a project on painting recognition using opencv-python.
Right now I am able to detect most of the paintings decently however the bounding boxes are rectangles that include a lot of background.
This is because the cv2.boundingRect() function finds the bounding rectangle with a perpendicular projection (afaik). However I want to find the best bounding box without detecting any background.

The main part of my code:

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

hue, saturation, value = cv2.split(hsv)
blurred_sat = cv2.GaussianBlur(saturation, (5, 5), 0)
edges = cv2.Canny(blurred_sat, 45, 100)

kernel = np.ones((3, 3), np.uint8)
dilate = cv2.dilate(edges, kernel, iterations=6)
erode = cv2.erode(dilate, kernel, iterations=2)
contours, hierarchy = cv2.findContours(erode, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

contours = sorted(contours, key=cv2.contourArea, reverse=True)[:10]

# cv2.drawContours(frame, contours, -1, (255, 255, 0), 3)
for contour in contours:
    area = cv2.contourArea(contour)
    if area >= 3000:
        x, y, w, h = cv2.boundingRect(contour)
        subImg = frame[y:y+h, x:x+w]
        cv2.rectangle(frame,
                      (x, y), (x + w, y + h),
                      (0, 255, 0),
                      2)

Current output image (video)
Desired output image with desired bounding box in red

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦太阳 2025-02-01 17:22:09

查找和排序轮廓后,您需要使用cv2.Minarearect()函数。这绘制了一个矩形,将每个轮廓包裹在每个轮廓的区域中:

import numpy as np

# portion of code to find and sort contours

for contour in contours:
    area = cv2.contourArea(contour)
    if area >= 3000:
        rect = cv2.minAreaRect(cnt)
        box = cv2.boxPoints(rect)
        box = np.int0(box)
        cv2.drawContours(frame, [box], 0, (0, 255, 0), 2)

注意: cv2.minarearect()返回旋转矩形的属性(中心,尺寸,尺寸,和旋转角)。 cv2.boxpoints()用于获得矩形的顶点。然后将其传递到cv2.drawContours()绘制它们中。

看看

文档

更新:

以下代码近似于四边形轮廓并在frage上绘制。变量value确定您希望近似值的强度:

# use a value between 0 and 1
value = 0.02
for c in contours:
    perimeter = cv2.arcLength(c, True)  
    approx = cv2.approxPolyDP(c, value*perimeter, True)    
    if len(approx) == 4:
        cv2.drawContours(frame, [approx], 0, (0, 0, 255), 5)

After finding and sorting the contours, you need to use cv2.minAreaRect() function. This draws a rectangle enclosing each contour with the least area:

import numpy as np

# portion of code to find and sort contours

for contour in contours:
    area = cv2.contourArea(contour)
    if area >= 3000:
        rect = cv2.minAreaRect(cnt)
        box = cv2.boxPoints(rect)
        box = np.int0(box)
        cv2.drawContours(frame, [box], 0, (0, 255, 0), 2)

Note: cv2.minAreaRect() returns properties of the rotated rectangle (center, dimensions and angle of rotation). cv2.boxPoints() is used to obtain the vertices of the rectangle. This is then passed into cv2.drawContours() to draw them.

Have a look at the documentation

For details on the algorithm:

Update:

The following code approximates a quadrilateral around a contour and draws it on frame. The variable value determines how strong you want your approximations to be:

# use a value between 0 and 1
value = 0.02
for c in contours:
    perimeter = cv2.arcLength(c, True)  
    approx = cv2.approxPolyDP(c, value*perimeter, True)    
    if len(approx) == 4:
        cv2.drawContours(frame, [approx], 0, (0, 0, 255), 5)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文