我有一个图像,我想做边缘检测并为其绘制边界框,我的问题是我的Python代码没有绘制边界框,我不确定它是否是这样,因为它无法检测到其中的任何对象它或者我只是画错了矩形。
这是我的尝试
import cv2
import numpy as np
img = cv2.imread("image1.jpg")
(B, G, R) = cv2.split(img)
img = cv2.Canny(B, 20, 100) # Blue channel gives the best box so far
# img = cv2.Canny(R, 20, 100)
# img = cv2.Canny(R, 20, 100)
ret,thresh = cv2.threshold(img,20,100,0)
contours,hierarchy = cv2.findContours(thresh, 1, 2)
cnt = contours[0]
M = cv2.moments(cnt)
for c in contours:
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.intp(box)
img = cv2.drawContours(img,[box],0,(0,0,255),2)
# display the image with bounding rectangle drawn on it
# cv2.namedWindow('Bounding Rectangle', cv2.WINDOW_KEEPRATIO)
cv2.imshow('Bounding Rectangle', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
这会产生这个图像
我期待这样的图像:
我的做法:
此方法可检测所有四个彩色方块。
# gray = im.mean(axis=(0,1), dtype=np.float32) # gray world
gray = np.median(im, axis=(0,1)).astype(np.float32) # majority vote
print(gray) # [137. 127. 140.]
balanced = (im / gray) * 0.8 # some moderate scaling so it's not "overexposed"
hsv = cv.cvtColor(balanced, cv.COLOR_BGR2HSV)
H,S,V = cv.split(hsv)
# squares nicely visible
为了比较,源的饱和通道,没有白平衡:
print(S.min(), S.max()) # 0.0 0.9125462
mask = (S >= 0.3)
(contours, _) = cv.findContours(mask.astype(np.uint8), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
hull = cv.convexHull(np.concatenate(contours))
rrect = cv.minAreaRect(hull)
# visualization
canvas = im.copy()
cv.drawContours(image=canvas, contours=contours, contourIdx=-1, color=(255,255,0), thickness=7)
# cv.drawContours(image=canvas, contours=[hull], contourIdx=-1, color=(255,255,0), thickness=7)
rrect_points = cv.boxPoints(rrect).round().astype(int)
cv.polylines(canvas, [rrect_points], isClosed=True, color=(0,255,255), thickness=3)
我对阈值进行了一些操作,并跳过了拆分通道以仅使用蓝色通道的步骤,并跳过使用
Canny
。尝试:
import cv2
import numpy as np
# Load the image
cimg = cv2.imread('bBox.jpg')
# Convert to grayscale
img = cv2.cvtColor(cimg, cv2.COLOR_BGR2GRAY)
# Apply threshold or other color segmentation
_, img = cv2.threshold(img, 95, 255, cv2.THRESH_BINARY)
# Find contours
contours , _ = cv2.findContours(img, 1, 2)
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
for cnt in contours :
# Fit a minimum area rectangle
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.intp(box)
# Draw the bounding box
cv2.drawContours(cimg, [box], 0, (0, 255, 0), 5)
# Show the image
cv2.imshow('Bounding Boxes', cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()
在我在代码中使用的源图像和带有结果边界框的图像下方:
如果您想要整体框,您可以重复使用找到的边界框坐标来提取您需要绘制所需框的这些坐标。
请注意,OpenCV 对象检测适用于白色对象,因此为了获得更好的结果并消除整个图像上的边界框,请使用:
img=cv2.bitwise_not(img)
在搜索轮廓之前反转图像。
下面的代码展示了原理如何绘制整体边界框(使用适当的更好的算法进行调整以覆盖更广泛的情况):
import cv2
import numpy as np
cimg = cv2.imread('bBox.jpg')
img = cv2.cvtColor(cimg, cv2.COLOR_BGR2GRAY)
_, img = cv2.threshold(img, 95, 255, cv2.THRESH_BINARY)
img=cv2.bitwise_not(img)
contours , _ = cv2.findContours(img, 1, 2)
bBoxes = []
for cnt in contours :
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.intp(box)
bBoxes += [ list(xy) for xy in list(box) ]
bBoxes=sorted(bBoxes)
bBox=np.array( [ bBoxes[1] ] + [ bBoxes[0] ] + [ bBoxes[-10] ] + [ bBoxes[-1] ])
cv2.drawContours(cimg, [bBox], 0, (0, 255, 0), 5)
# Show the image
cv2.imshow('Rotated Bounding Box', cimg)
cv2.waitKey(0)
图像质量不是很好。 GaussianBlur 用于使边缘更加清晰并消除噪音
import cv2
import numpy as np
img = cv2.imread("image1.jpg")
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_blur = cv2.GaussianBlur(img_gray, (5,5), 0)
_, img_thresh = cv2.threshold(img_blur, 120, 255, cv2.THRESH_BINARY) # cv2.THRESH_BINARY + cv2.THRESH_OTSU can use
cv2.imshow("thresh", img_thresh)
contours,hierarchy = cv2.findContours(img_thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
M = cv2.moments(cnt)
for c in contours:
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.intp(box)
img = cv2.drawContours(img,[box],0,(0,0,255),2)
# # display the image with bounding rectangle drawn on it
cv2.imshow('Bounding Rectangle', img)
cv2.waitKey(0)
cv2.destroyAllWindows()