Python3采用Qt5逐帧获取点击坐标位置

目标

用Python实现对一个序列的所有图片逐个进行焦点标记,通过获取鼠标点击图像中的位置坐标实现。

工具

PyQt5对于UI操作以及获取鼠标事件信息是非常方便的,而采用Opencv处理图像也极为便利。

Show me the code

# require Python3.6+ & PyQt5 & OpenCV
# pip install PyQt5
# pip install python-opencv

import cv2
import numpy as np
import glob

import sys
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtWidgets import QLabel
from PyQt5.QtGui import QIcon, QPixmap


class WindowCapture(QtWidgets.QMainWindow):
    def __init__(self, files, fp_focus):
        super().__init__()
        self.start_pos = None
        self.stop_pos = None
        self.files = files
        self.file_id = 0
        self.fp_focus = fp_focus
        # setup the scale
        if len(self.files) > 0:
            im_ = cv2.imread(self.files[0], -1)
            self.im_w = im_.shape[1]
            self.im_h = im_.shape[0]
        self.initUI()
    def mousePressEvent(self, QMouseEvent):
        self.start_pos = QMouseEvent.pos()
    def mouseReleaseEvent(self, QMouseEvent):
        self.stop_pos = QMouseEvent.pos()
        d = (self.stop_pos.x() - self.start_pos.x())\
        *(self.stop_pos.x() - self.start_pos.x()) + \
        (self.stop_pos.y() - self.start_pos.y())*\
        (self.stop_pos.y() - self.start_pos.y())
        d = np.sqrt(d)
        if d < 1: # not moved
            self.saveFocus()
            self.showNextImage()
    def keyPressEvent(self, event):
        if event.key() == ord('q') or event.key() == ord('Q'):
            self.close()
    def initUI(self):
        self.setGeometry(100, 100, 800, 600)
        self.setWindowTitle('Capture Focus')
        self.setWindowFlags(self.windowFlags() | QtCore.Qt.FramelessWindowHint)
        
        # show the first image
        self.image_container = QLabel(self)
        self.im_ = QPixmap(self.files[self.file_id])
        self.im_ = self.im_.scaled(800, 600, QtCore.Qt.KeepAspectRatio)
        self.image_container.setPixmap(self.im_)
        self.image_container.resize(800, 600)
        self.show()
    def saveFocus(self):
        f_x = int(self.stop_pos.x() * self.im_w / 800.0)
        f_y = int(self.stop_pos.y() * self.im_h / 600.0)
        if self.file_id == 0:
            self.fp_focus.write('%d, %d' % (f_x, f_y))
        else:
            self.fp_focus.write('\n%d, %d' % (f_x, f_y))
    def showNextImage(self):
        if self.file_id == len(self.files)-1:
            self.close()
        else:
            self.file_id += 1
            self.im_ = QPixmap(self.files[self.file_id])
            self.im_ = self.im_.scaled(800, 600, QtCore.Qt.KeepAspectRatio)
            self.image_container.setPixmap(self.im_)

if __name__ == '__main__':
    root_dir = 'Bokeh'
    focus_file = 'focus.txt'
    files = glob.glob(root_dir + '/*.png')
    files.sort()
    app = QtWidgets.QApplication(sys.argv)
    fp_focus = open(focus_file, 'wt')
    ex = WindowCapture(files, fp_focus)
    sys.exit(app.exec_())
    fp_focus.close()

注意到程序中为了便于显示超过显示器分辨率的图像,在程序中将输入的图像缩小到800x600,因此点击的坐标需要反向转换回去。

posted @ 2021-07-20 15:39  xchk138  阅读(701)  评论(0)    收藏  举报