使用OpenCV分离对象计数

2024-09-28 19:35:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在使用OpenCV来检测方形障碍物。到目前为止,这是我应用过滤器和canny后得到的图像。Canny Result

我试图确定的障碍是水平的,三个垂直的矩形是地板上的引导线。我的目标是只保留水平矩形,将其与其他矩形分开,但在应用“查找轮廓”后,我只得到一个包含所有形状的对象。这是我一直在使用的代码,以便按面积仅为最大的矩形添加鳍:

# find the biggest countour (c) by the area
    if contours != 0:
        if not contours:
            print("Empty")

        else:
            bigone = max(contours, key=cv2.contourArea) if max else None
            area = cv2.contourArea(bigone)
            if area > 10000:
                x, y, w, h = cv2.boundingRect(bigone)
                cv2.rectangle(img, (x, y), (x+w, y+h), (0, 0, 255), 2)
                cv2.putText(img, "Obstacle", (x+w/2, y-20),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

                pts = np.array(
                    [[[x, y], [x+w, y], [x+w, y+h], [x, y+h]]], dtype=np.int32)
                cv2.fillPoly(mask, pts, (255, 255, 255))
                #values = img[np.where((mask == (255, 255, 255)).all(axis=2))]
                res = cv2.bitwise_and(img, mask)  # View only the obstacle
                obs_area = w*h
                print(obs_area)
                if obs_area <= 168000:

                    command_publisher.publish("GO")
                    cv2.putText(
                        img, "GO", (380, 400), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 255), 1)

                else:
                    command_publisher.publish("STOP")
                    cv2.putText(img, "STOP", (380, 400),
                                cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 255), 1)

                # show the output image
                cv2.imshow("Image", img)
                cv2.waitKey(1)

这就是我得到的结果:

Result

有没有办法用某种过滤器或算法将我的障碍物从地板上的线条中分离出来

以下是要使用的示例图像:

Test Image


Tags: theimgifnpmaskareacv2else
2条回答

在您的图像中,问题似乎是白色矩形。我的方法是检查每一行,如果这一行包含许多接近白色的像素(255255),那么就把这一行变成黑色

这是我的密码:

import cv2
import numpy as np
import random as rng


img=cv2.imread("/ur/image/directory/obstacle.png")
height, width, channels = img.shape
cv2.imshow('Source',img)

# Check each line and eliminate white rectangles(if line consist white pixels more than limit)
for x in range(0,height):
    white_counter = 0
    for y in range(0,width):
        if  img[x,y,0] >= 180 and img[x,y,1] >= 180 and img[x,y,2] >= 180: 
            white_counter = white_counter + 1

    if white_counter>10:
        for y in range(0,width):
            img[x,y,0] = 0
            img[x,y,1] = 0
            img[x,y,2] = 0

cv2.imshow('Elimination White Rectangles', img)

# Find contours and draw rectangle for each

src_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
threshold = 300
canny_output = cv2.Canny(src_gray, threshold, threshold * 2)
contours, _ = cv2.findContours(canny_output, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

contours_poly = [None]*len(contours)
boundRect = [None]*len(contours)
for i, c in enumerate(contours):
        contours_poly[i] = cv2.approxPolyDP(c, 3, True)
        boundRect[i] = cv2.boundingRect(contours_poly[i])

rng.seed(12345)
drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)

for i in range(len(contours)):
        color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))
        cv2.rectangle(drawing, (int(boundRect[i][0]), int(boundRect[i][1])), \
          (int(boundRect[i][0]+boundRect[i][2]), int(boundRect[i][1]+boundRect[i][3])), color, 2)

cv2.imshow('Output', drawing)

cv2.waitKey(0)
cv2.destroyAllWindows()

消除白色矩形:

enter image description here

结果:

enter image description here

下面是使用Python/OpenCV实现这一点的一种方法

 - Read the input
 - Convert to HSV and extract only the saturation channel (black/white/gray have zero saturation)
 - Threshold
 - Apply morphology open and close to remove the extranous white regions
 - Get the contour and approximate to simple polygon
 - Draw the polygon on the input
 - Save the results


输入:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('board.png')

# convert to HSV and extract saturation channel
sat = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)[:,:,1]

# threshold
thresh = cv2.threshold(sat, 90, 255, 0)[1]

# apply morphology close to fill interior regions in mask
kernel = np.ones((7,7), np.uint8)
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = np.ones((13,13), np.uint8)
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)

# get contours (presumably only 1) and fit to simple polygon (quadrilateral)
cntrs = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
c = cntrs[0]
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.05 * peri, True)

# draw polygon on input
result = img.copy()
cv2.polylines(result, [np.int32(approx)], True, (0,0,255), 1, cv2.LINE_AA)


# write result to disk
cv2.imwrite("board_saturation.png", sat)
cv2.imwrite("board_thresh.png", thresh)
cv2.imwrite("board_morph.png", morph)
cv2.imwrite("board_contour.png", result)

# display it
cv2.imshow("IMAGE", img)
cv2.imshow("SAT", sat)
cv2.imshow("THRESH", thresh)
cv2.imshow("MORPH", morph)
cv2.imshow("RESULT", result)
cv2.waitKey(0)


饱和通道图像:

enter image description here

阈值图像:

enter image description here

形态学清理图像:

enter image description here

输入时的轮廓:

enter image description here

相关问题 更多 >