[英]OpenCV: how to detect and identify objects on solid color background using chroma key and contour detection
I have a camera (calibrated, warped with OpenCV) facing a flat surface top down.我有一个相机(校准,用 OpenCV 扭曲)面向一个平面自上而下。 The surface will be a single solid color.
表面将是单一的纯色。
I want to be able to identify objects lying on the surface and determine what they are.我希望能够识别表面上的物体并确定它们是什么。 The objects are metal parts varying from 15mm to 100mm made of the same alloy (so same color).
这些物体是由相同合金(因此颜色相同)制成的从 15 毫米到 100 毫米不等的金属部件。 The parts will generally be placed top down on the surface, but handling lying parts would be a nice to have.
零件通常会自上而下放置在表面上,但处理躺着的零件会很不错。 What I have so far:
到目前为止我所拥有的:
What my future setup should look like:我未来的设置应该是什么样子:
I want the algorithm to identify all 3 screws as screws in the easiest way possible, and return their outline in pixels.我希望算法以最简单的方式将所有 3 个螺钉识别为螺钉,并以像素为单位返回它们的轮廓。 I also want it to be able to differentiate between completely different screws or parts of similar colour and size.
我还希望它能够区分完全不同的螺钉或颜色和尺寸相似的部件。
I am a noob in OpenCV, so I really would like to hear techniques with pro's and cons from people with experience.我是 OpenCV 的菜鸟,所以我真的很想听听有经验的人的优点和缺点的技术。 How would you approach this problem effectively?
你将如何有效地解决这个问题?
Uncertain why this got downvoted, but after a week of experimenting, I found a really good way to find objects on a solid background in OpenCV:不确定为什么这被否决了,但经过一周的实验,我找到了一个非常好的方法来在 OpenCV 中的纯色背景上找到对象:
Use chroma key correction to remove the background with function cv2.inRange使用色度键校正去除带有 function cv2.inRange 的背景
Invert colours so that found objects are white and everything else is black with image = cv2.bitwise_not(image)反转颜色,以便找到的对象是白色的,其他一切都是黑色的 image = cv2.bitwise_not(image)
Use contour detection with the cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE parameter as the 'EXTERNAL' parameter will not work: cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)使用带有 cv2.RETR_LIST、cv2.CHAIN_APPROX_NONE 参数的轮廓检测,因为“EXTERNAL”参数将不起作用:cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
return both the area (number of pixels) and the bounding box of all found contours.返回所有找到的轮廓的区域(像素数)和边界框。 The combination of these is actually very powerful for identifying most 2D objects in my case.
在我的案例中,这些组合对于识别大多数 2D 对象实际上非常强大。
If you have an aruco tag or other element with known real world mm sizes in your picture, it becomes easy to convert the area to mm2.如果您的图片中有 aruco 标签或其他已知真实世界 mm 尺寸的元素,则将面积转换为 mm2 变得很容易。 Function for finding an aruco tag:
Function 用于查找 aruco 标签:
arucoDict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_4X4_50) arucoParams = cv2.aruco.DetectorParameters_create() (corners, ids, rejected) = cv2.aruco.detectMarkers(image, arucoDict, parameters=arucoParams) arucoDict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_4X4_50) arucoParams = cv2.aruco.DetectorParameters_create() (corners, ids, denied) = cv2.aruco.detectMarkers(image, arucoDict, parameters=arucoParams)
import cv2
import numpy as np
def getContours(img,imgContour):
""" DRAWS AND FINDS CONTOURS, THEN RETURNS a list of lists incl x0, y0, w, h"""
contour_list = []
contours, hierarchy = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
# print('contours:', contours)
for cnt in contours:
area = cv2.contourArea(cnt)
areaMin = 200
if area > areaMin and area < 5000:
cv2.drawContours(imgContour, cnt, -1, (255, 0, 0), 7)
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
# print(len(approx))
x , y , w, h = cv2.boundingRect(approx)
print('contour bounding:', x,y,w,h)
center_x = int(x + w/2)
center_y = int(y + h/2)
cv2.circle(imgContour,(center_x, center_y), 5, (0, 0, 255), 5)
cv2.rectangle(imgContour, (x , y ), (x + w , y + h ), (0, 255, 0), 5)
cv2.putText(imgContour, "Points: " + str(len(approx)), (x + w + 20, y + 20), cv2.FONT_HERSHEY_COMPLEX, .7,
(0, 255, 0), 2)
cv2.putText(imgContour, "Area: " + str(int(area)), (x + w + 20, y + 45), cv2.FONT_HERSHEY_COMPLEX, 0.7,
(0, 255, 0), 2)
if area < 3500:
cv2.putText(imgContour, "THIS IS A SMALL PART" , (x + w + 20, y + 70), cv2.FONT_HERSHEY_COMPLEX, 0.7,
(0, 255, 0), 2)
contour_list.append([x,y,w,h])
return contour_list
while True:而真:
img = cv2.imread('yellowcropped.jpg', 1)
image_original = img.copy()
lower_blue = np.array([160, 140, 15]) ##[R value, G value, B value]
upper_blue = np.array([255, 235, 60])
image_copy = np.copy(img)
image_copy = cv2.cvtColor(image_copy, cv2.COLOR_BGR2RGB)
mask = cv2.inRange(image_copy, lower_blue, upper_blue)
mask = cv2.bitwise_not(mask)
img = cv2.cvtColor(mask, cv2.COLOR_BGR2RGB)
# img = image
imgContour = image_original.copy()
getContours(mask,imgContour)
imgStack = stackImages(0.6,([mask],[imgContour]))
# cv2.imshow("Result", imgStack)
cv2.imshow('Img_contour', imgContour)
# cv2.setMouseCallback("Img_contour", mouse_callback)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.