获得第一个和最后一个位置

2024-04-26 02:16:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我用OpenCV创建了一个图像的遮罩

Mask of image

我想知道是否有可能得到第一次和最后一次出现的白色像素的X和Y位置,并将其存储为变量,请参见下面的图片。你知道吗

enter image description here

我想我可以将图像转换成一个numpy数组,然后循环遍历每一行,将位置与前一行进行比较,但是对于较大的图像,这可能需要占用大量CPU。你知道吗

有没有更快捷的方法获得信息?你知道吗

我可以发布代码来显示上面的内容,但潜在的问题是是否有比扫描和比较每一行更快的方法。你知道吗


Tags: 方法代码图像numpy信息内容图片像素
3条回答

如果您想尝试一个基于numpy的实现。你知道吗

import cv2
import numpy as np

image = cv2.imread('blob.png', cv2.IMREAD_GRAYSCALE)

# Make sure image is binary (the one you posted was not, probably due to interpolation)
_, image = cv2.threshold(image, 50, 255, cv2.THRESH_BINARY)

# Find top left and bottom right coords for non-background pixels
active_pixels = np.stack(np.where(image))
top_left = np.min(active_pixels, axis=1).astype(np.int32)
bottom_right = np.max(active_pixels, axis=1).astype(np.int32)

# Plot them
for keypoint in [top_left, bottom_right]:
    y, x = keypoint
    cv2.drawMarker(image, (x, y), 255, markerType=cv2.MARKER_TILTED_CROSS,
                   markerSize=10, thickness=2)

cv2.imshow('image', image)
cv2.waitKey(0)

输出:

enter image description here

下面是在Python/OpenCV中获取对象边界的角点的另一种方法。你知道吗

  • 阅读图像
  • 转换为灰度
  • 门槛
  • 应用“打开”去除单独的白点
  • 获取轮廓
  • 获取轮廓的边界框
  • 使用numpy绘制点(在本例中,3个像素块用于强调)
  • 保存结果

输入:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('odd_shape.png')

# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# threshold
thresh = cv2.threshold(gray,5,255,cv2.THRESH_BINARY)[1]

# apply open morphology to remove extraneous white circles
kernel = np.ones((15,15), np.uint8)
thresh_cleaned = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

# get contours (presumably just one around the nonzero pixels) 
# then get bounding rectangle
contours = cv2.findContours(thresh_cleaned, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
for cntr in contours:
    x,y,w,h = cv2.boundingRect(cntr)
    top_left=(x,y)
    bottom_right=(x+w-1,y+h-1)
    print('top left=',top_left)
    print('bottom right=',bottom_right)

# copy image for drawing bounding box
bounding_box = img.copy()

# draw bounding box on image
cv2.rectangle(bounding_box, top_left, bottom_right, (0,0,255), 1)

# copy image for drawing (3px wide) points 
points = img.copy()

# use numpy to draw 3px wide points on image
points[y-1:y+2,x-1:x+2]=[0,0,255]
points[y+h-2:y+h+1,x+w-2:x+w+1]=[0,0,255]

cv2.imshow("thresh", thresh)
cv2.imshow("thresh_cleaned", thresh_cleaned)
cv2.imshow("bounding_box", bounding_box)
cv2.imshow("points", points)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save image with points drawn
cv2.imwrite('odd_shape_points.png',points)


点(x,y坐标):

top left = (33, 20)
bottom right = (179, 179)


阈值图像:

enter image description here

已清除的重建图像:

enter image description here

图像上的边界框:

enter image description here

在图像上绘制的点:

enter image description here

实现这一点的一种方法是使用^{}。你知道吗

假设您的输入仅由10组成,代码如下:

import numpy as np
import scipy as sp
import scipy.ndimage


arr = np.array([[0, 0, 0, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]])
print(arr)
# [[0 0 0 0]
#  [0 1 1 0]
#  [0 0 1 0]
#  [0 1 0 0]
#  [0 0 0 0]]


slicings = sp.ndimage.find_objects(arr)
print(slicings)
# [(slice(1, 4, None), slice(1, 3, None))]

# : compute corners
# slicings information is: `slicings[label_index][dimension_index]`
top_left_corner = slicings[0][0].start, slicings[0][1].start
bottom_right_corner = slicings[0][0].stop - 1, slicings[0][1].stop - 1
print(top_left_corner)
# (1, 1)
print(bottom_right_corner)
# (3, 2)

实际上find_object()更为复杂,可以用于不同的标签,请查看其文档,了解如何在不同的场景中使用它的更多信息。你知道吗

如果您的输入不是二进制的,您可以使用比较使其成为二进制的,例如arr > 0将产生一个布尔数组(假设arr是NumPy数组)。你知道吗

相关问题 更多 >