【问题标题】:How to identify distinct objects in image in OpenCV Python如何在 OpenCV Python 中识别图像中的不同对象
【发布时间】:2019-12-03 14:32:29
【问题描述】:

我正在尝试在 OpenCV 中识别图像中的单独对象。到目前为止,我已经将图像打开到 NumPy 数组中并对其进行阈值处理,因此它是二进制的。这是它的样子:

Original Image

我正在尝试识别不同对象所在的 NumPy 数组索引,例如分割。这是我想要实现的目标: End goal(我没有费心为这张图片中的每个对象都涂上不同的颜色,但你明白了)

本质上,我试图将每个被视为“对象”的像素簇标记为一个单独的类,并为这些类中的每一个生成一个数组索引列表。我尝试过使用 OpenCV 的 connectedComponentsWithStats,但我不知道如何为此图像中每个对象的位置生成数组索引列表。我怎样才能做到这一点?

【问题讨论】:

标签: python numpy opencv


【解决方案1】:

您面对的是connected component labeling,所以您可以使用的最佳功能正是您提到的connectedComponentsWithStats

但是,它的使用一开始可能会有点混乱。在这里您可以找到一个工作示例。

import cv2
import numpy as np

# Load the image in grayscale
input_image = cv2.imread(r"satellite.png", cv2.IMREAD_GRAYSCALE)

# Threshold your image to make sure that is binary
thresh_type = cv2.THRESH_BINARY + cv2.THRESH_OTSU
_, binary_image = cv2.threshold(input_image, 0, 255, thresh_type)

# Perform connected component labeling
n_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(binary_image,
                                                                      connectivity=4)

# Create false color image
colors = np.random.randint(0, 255, size=(n_labels , 3), dtype=np.uint8)
colors[0] = [0, 0, 0]  # for cosmetic reason we want the background black
false_colors = colors[labels]

cv2.imshow('binary', binary_image)
cv2.imshow('false_colors', false_colors)
cv2.waitKey(0)

二进制图像:

图像标记(假色):

centroids 变量已包含每个标记对象的质心 (x, y) 坐标。

false_colors_draw = false_colors.copy()
for centroid in centroids:
    cv2.drawMarker(false_colors_draw, (int(centroid[0]), int(centroid[1])),
                   color=(255, 255, 255), markerType=cv2.MARKER_CROSS)
cv2.imshow('false_colors_centroids', false_colors_draw)
cv2.waitKey(0)

质心:

如您所见,它们非常多。如果您只想保留较大的对象,您可以 i) 在开始时对二值图像使用形态学运算,或者 ii) 使用 stats 中已包含的区域信息。

MIN_AREA = 50
false_colors_draw = false_colors.copy()
for i, centroid in enumerate(centroids[1:], start=1):
    area = stats[i, 4]
    if area > min_area:
        cv2.drawMarker(false_colors_draw, (int(centroid[0]), int(centroid[1])),
                       color=(255, 255, 255), markerType=cv2.MARKER_CROSS)

质心(按区域过滤):

【讨论】:

  • 每个“标签”的索引存储在哪里?在标签数组中?标签中的每一项都是表示每个标签形状的数组吗?
  • label 数组是一个索引图像,其中每个像素的值等于其标签。例如。如果某个 blob 的值为 1,而另一个 blob 的值为 34,则表示这两个对象未连接
  • 您知道将每个标签提取为自己的二进制数组的简单方法吗?我正在使用的图像是 12000 x 10000,所以 np.where 不是特别有效。
【解决方案2】:

使用cv2.findContourscv2.drawContours

编辑:代码

import cv2
import numpy as np
import random as rng

im = cv2.imread('YourImagePath\\test2.png')
gray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 113, 255, 0)
contours, hierarchy = 
cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)[-2:]
idx =0

for cnt in contours:
    idx += 1
    x,y,w,h = cv2.boundingRect(cnt)
    roi=im[y:y+h,x:x+w]
    color = (rng.randint(0, 256), rng.randint(0, 256), rng.randint(0, 256))
    #cv2.rectangle(im,(x,y),(x+w,y+h),color,2)
    cv2.drawContours(im,[cnt],0 ,color,-1)
cv2.imshow('img',im)
cv2.waitKey(0)

【讨论】:

  • 请把源代码作为文本,而不是图片。
猜你喜欢
  • 1970-01-01
  • 2016-05-12
  • 1970-01-01
  • 1970-01-01
  • 2014-06-28
  • 2020-12-08
  • 2022-01-01
  • 2018-11-19
  • 1970-01-01
相关资源
最近更新 更多