【问题标题】:How to find the center of black objects in an image with python opencv?如何使用 python opencv 在图像中找到黑色物体的中心?
【发布时间】:2026-02-17 23:30:01
【问题描述】:

我在寻找白色背景上黑色物体的轮廓时遇到了问题。

在这里我添加了一个图像示例。 现在我需要找到黑色区域的中心,我使用以下代码。

im = cv2.imread(img)
plt.imshow(im)
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.threshold(im, 60, 255, cv2.THRESH_BINARY_INV)
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

但是它给出了一个类似

的错误

TypeError: Expected Ptr for argument 'image'" 用于 cv2.findeContours() 的图像参数。

我该如何解决这个问题?或者如果您有任何其他想法如何找到我想听的黑色区域的中心。谢谢。

【问题讨论】:

  • 使用thresh = cv2.threshold(im, 60, 255, cv2.THRESH_BINARY_INV)[1],参见。 threshold 的返回值。
  • 对不起,这是我第一次使用 Opencv,你是什么意思 cf。阈值的返回值?
  • 但是你知道,return statements 通常是什么?当调用cv2.threshold(...) 并将结果转发到单个变量thresh 时,这将是一个由retvaldst 组成的元组。当调用cv2.threshold(...)[1]时,你只会得到dst,从而转发到thresh,你的thresh是实际的阈值图像。
  • 谢谢我明白你的意思,它有点解决了与阈值相关的错误,谢谢。但 cv2.findContours() 出现新错误“错误:OpenCV(4.2.0) C:\projects\opencv-python\opencv\modules\imgproc\src\contours.cpp:197: error: (-210:Unsupported格式或格式组合)[开始]FindContours 在模式时仅支持 CV_8UC1 图像!= CV_RETR_FLOODFILL 否则仅在函数 'cvStartFindContours_Impl' 中支持 CV_32SC1 图像“据我所知,我应该更改图像的模式吗?
  • 你的原图是三通道图像,所以thresh也是三通道,cv2.findContours(...)不支持。例如,使用thresh = cv2.threshold(gray, ...) 而不是thresh = cv2.threshold(im, ...)。 (以前没有注意到...)

标签: python image opencv image-processing computer-vision


【解决方案1】:

你在正确的轨道上。当您对图像执行find contours 时,OpenCV 预计要检测的前景对象为白色,背景为黑色。 为此,您可以使用Otsu's thresholdcv2.THRESH_BINARY_INV 参数来得到白色的物体。从这里我们可以通过计算centroidcv2.moments 来找到轮廓并找到每个区域的中心。结果如下:

二值图像

对象的中心以蓝色绘制,边界框为绿色。您可以通过检查cXcY 变量来获取每个轮廓的坐标。

您可以使用 Numpy 切片裁剪每个单独的 ROI,然后使用 cv2.imwrite 保存

代码

import cv2
import numpy as np

# Load image, grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread('1.png')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find contours
ROI_number = 0
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    # Obtain bounding rectangle to get measurements
    x,y,w,h = cv2.boundingRect(c)

    # Find centroid
    M = cv2.moments(c)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])

    # Crop and save ROI
    ROI = original[y:y+h, x:x+w]
    cv2.imwrite('ROI_{}.png'.format(ROI_number), ROI)
    ROI_number += 1

    # Draw the contour and center of the shape on the image
    cv2.rectangle(image,(x,y),(x+w,y+h),(36,255,12), 4)
    cv2.circle(image, (cX, cY), 10, (320, 159, 22), -1) 

cv2.imwrite('image.png', image)
cv2.imwrite('thresh.png', thresh)
cv2.waitKey()

【讨论】:

  • 谢谢,我解决了这个问题。现在我需要以相同的大小裁剪这些图像,我使用了 numpy 切片,但它给出了一个错误,例如“TypeError: string indices must be integers”。我该如何解决这个问题,或者是否有任何其他方法可以用于裁剪?
  • 检查更新,您可以使用 Numpy 切片并使用 cv2.imwrite 保存图像