【问题标题】:CV, detecting object size in photo (Python) [closed]CV,检测照片中的对象大小(Python)[关闭]
【发布时间】:2021-10-03 17:48:21
【问题描述】:

我是物理学家,不是专业程序员。所以我需要最简单、最短的解决方案来解决我的问题。我有这样的照片:

每个球的大小是 1 厘米,所以我应该检测它们,计算它的大小(以像素为单位)并找到比例。然后我将计算每两个球之间的距离。由于照片数量众多,我们不能使用手动标记。所以我想编写自动执行它的python脚本。 Сan你建议我可以解决我的问题的python库或框架。也许有一些现成的解决方案可以检测对比背景下的几何图形。

【问题讨论】:

  • OpenCV 是一个很好的 python 图像处理库,可以完成这样的任务。看看这篇文章……pyimagesearch.com/2016/03/28/… 或者这个 github 仓库……github.com/Practical-CV/Measuring-Size-of-Objects-with-OpenCV……你只需要一个参考点,这意味着你必须告诉 OpenCV 一厘米有多少像素。计算这些球之间的距离更具挑战性。
  • 下面的答案都很好,只是想提醒你,如果你能让球与背景有更多的对比(纯白还是蓝屏?),程序会做得更好。

标签: python image-processing computer-vision


【解决方案1】:

这是 Python/OpenCV 中一个非常简单的方法。

 - Read the input image
 - Convert to HSV and save the Hue channel
 - Threshold at 165 since the beads are on the blue side of red and so have a high value out of 180. (OpenCV hues range from 0 to 180, which is half the normal 0 to 360 range).
 - Apply morphology open and close to remove excess white spots and fill holes.
 - Find external contours
 - Loop over each contour and get the minimum enclosing circles  radii and center
 - Draw the circles on a copy of the input
 - Compute the average radius
 - Save results and print average radius

输入:

import cv2
import numpy as np

# Read image
img = cv2.imread('beads.jpg')

# Convert to HSV and keep the hue channel
hue = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)[:,:,0]

# beads are red but on the blue side, so very bright hues
# so threshold hue at 165 (out of 180)
thresh = cv2.threshold(hue, 165, 255, cv2.THRESH_BINARY)[1]

# apply morphology to fill beads and remove excess spots
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (6,6))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)

# get contours and enclosing circles
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
circles = img.copy()
num_circles = len(contours)
ave = 0
for cntr in contours:
    center, radius = cv2.minEnclosingCircle(cntr)
    cx = int(round(center[0]))
    cy = int(round(center[1]))
    rr = int(round(radius))
    # draw enclosing circle over beads
    cv2.circle(circles, (cx,cy), rr, (0, 255, 0), 2)
    # cumulate radii for average
    ave = ave + radius

# print average radius
ave_radius = ave / num_circles
print("average radius:", ave_radius)
print ("number of circles:", num_circles)

# save results
cv2.imwrite('beads_thresh.jpg', thresh)
cv2.imwrite('beads_morph.jpg', morph)
cv2.imwrite('beads_circles.jpg', circles)

cv2.imshow('thresh', thresh)
cv2.imshow('morph', morph)
cv2.imshow('circles', circles)
cv2.waitKey(0)
cv2.destroyAllWindows()

阈值图像:

形态清洁图像:

输入的圆圈:

平均半径和计数:

average radius: 13.95605175635394
number of circles: 34

【讨论】:

    【解决方案2】:

    Python 包opencv-python 非常适合这项任务。

    基于颜色的图像分割应该可以正常工作,您可以将其与边缘检测相结合,因为球的边缘定义明确。

    有很多关于事物细分的 Stack Overflow 问题可能会给您带来启发:hereherehere

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-25
      • 2020-12-23
      • 1970-01-01
      • 2011-04-27
      • 2020-08-03
      • 2014-09-25
      • 2022-07-08
      • 1970-01-01
      相关资源
      最近更新 更多