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

2024-06-16 11:41:24 发布

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

我希望能够用鼠标光标在程序中显示的图像上拖动自由形状选择,并存储选定区域内点的坐标,以便用于其他功能。在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将包含选定点的坐标。 更快的方法应该是使用鼠标创建一个自由形状区域,并将像素坐标存储在该区域内。 有什么建议吗? 提前谢谢


Tags: 函数图像程序功能区域plt像素鼠标
1条回答
网友
1楼 · 发布于 2024-06-16 11:41:24

您可以使用OpenCV Contours and masking algorithms,通过在这个bounding rectangle(counter) and mask之间使用Bitwise AND operation,我们可以从图像中裁剪出多边形。
在编写和运行此代码之前,这里有几点需要注意

链接用于图像

cv2.boundingRect => It will create bounding rectangle look at image for best visualization
With and Without Bounding Rectangle

cv2.drawContours => It will update mask where ever points lie inside our counter.
Mask with and Without Contours extract

cv2.bitwise_and => For this you can refer to :
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)

相关问题 更多 >