Python Tkinter用鼠标在图像上选择一个区域并存储所选区域的坐标



我希望能够在我的程序中显示的图像上用鼠标光标拖动自由形状选择,并存储所选区域内点的坐标,以便用于其他功能。在python3中怎么做?一般来说,我使用ginput函数来存储像素坐标。

fig, ax=plt.subplots()
ax.imshow(img,cmap="gray")
plt.show()
yroi = plt.ginput(0,0)
yroi = np.array(yroi)
yroi = yroi.astype(int)

yroi将包含所选点的坐标。更快的方法应该是使用鼠标创建一个自由形状区域,并将像素坐标存储在该区域内。一些建议吗?提前感谢

您可以使用OpenCV Contours and masking algorithms,通过在bounding rectangle(counter) and mask之间使用Bitwise AND operation,我们可以从图像中裁剪出多边形。
在获取并运行这段代码之前,需要注意以下几点:

图片链接

cv2。boundingRect =比;它将创建一个边界矩形查看图像以获得最佳的可视化效果
有和没有边界矩形

cv2。drawContours =比;它将在计数器内的任何位置更新掩码。
带和不带轮廓的蒙版提取

cv2。bitwise_and =比;关于这一点,你可以参考:
Stackoverflow Discussion over cv2。Bitwise_and (img,img,mask = mask)

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as img
import matplotlib.patches as patches 
import cv2
image_file = 'photo.jpg'
def selection(s):
plt.title(s, fontsize=16)
plt.axis('off')
plt.draw()
# =========   Saving Click Point using ginput method   =========
while True:
data = []
while len(data) < 3:
image = img.imread(image_file)
fig, ax=plt.subplots()
ax.imshow(image,cmap="gray")
selection('Free Form Selection')
data = np.asarray(plt.ginput(0, timeout=-1))
if len(data) < 3:
selection('Free Form Selection')

# =========   Counter-Dimension   =========        
minXY = data.min(axis= 0)
maxXY = data.max(axis= 0)
delXY = maxXY - minXY

# =========   Counter with Free-Form Selection   =========
counter = plt.fill(data[:, 0], data[:, 1], '#f0f0f0', edgecolor='#000000', linewidth= 0.5)
rect = patches.Rectangle(minXY, delXY[0], delXY[1], linewidth= 0.5, edgecolor='#000000', facecolor="none") 

# =========   Add the patch to the Axes   ========= 
ax.add_patch(rect) 
selection('😁😁😁     😁😁😁     😁😁😁')
if plt.waitforbuttonpress():
break
# Get rid of fill
for c in counter:
c.remove()
# ========= Saving Point of Polygon to CSV file =========
np.savetxt('data.csv', data, delimiter=',')

# =========   Using OpenCV We can crop polygon of Image  =========
img = cv2.imread(image_file)
pts = np.array(data, dtype='int32')             # => datatype should be int32
# =========    Crop the Bounding Rectangle  =========
rect = cv2.boundingRect(pts)
x,y,w,h = rect
croped = img[y:y+h, x:x+w].copy()
# =========   Making Mask  =========
pts = pts - pts.min(axis=0)
mask = np.zeros(croped.shape[:2], np.uint8)
cv2.drawContours(mask, [pts], -1, (255, 255, 255), -1, cv2.LINE_AA)
# =========   BitWise Operation   =========
dst = cv2.bitwise_and(croped, croped, mask=mask)
# =========   Final Result  =========
cv2.imwrite("dst.png", dst)
img = cv2.imread('dst.png')
cv2.imshow('Image', img)
cv2.waitKey(0)

相关内容

最新更新