基于PySimpleGUI,Opencv,和MatplotLib实现图片中物体的距离测量
欢迎交流学习
功能描述
基于PySimpleGUI,Opencv,和MatplotLib实现图片中物体的距离测量,
- 点击Browse,选取图片路径;
- 点击draw, 显示图片;
- 填写分辨率,例如,填写100,表示1个像素为100个距离单位,默认为1;
- 双击鼠标左键选取起始点, start-xxx-xxx
- 双击鼠标右键选取终点, end-xxx-xxx, 并计算距离, result-xxxx
模块功能
import PySimpleGUI as psg
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.backend_bases import MouseEvent, MouseButton
import cv2
设计思路
代码实现
"""
@author:bjxyc@qq.com
@file:chapter_15_maoplotlib.py
@time:2023/12/27
Python Version:
pip国内源:
清华大学:https://pypi.tuna.tsinghua.edu.cn/simple
阿里云:https://mirrors.aliyun.com/pypi/simple/
"""
import PySimpleGUI as psg
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.backend_bases import MouseEvent, MouseButton
import cv2
class MyApp:
def __init__(self):
self.img = None
self.widget()
self.win = psg.Window('demo', layout=self.layout(), location=(10, 10))
self.win.finalize()
self.tk_fig = FigureCanvasTkAgg(self.fig, self.cvs.TKCanvas)
self.tool = NavigationToolbar2Tk(self.tk_fig, self.cvs.TKCanvas)
self.tk_fig.get_tk_widget().pack()
self.event = None
self.value = None
# 控件
def widget(self):
self.tt = psg.Text('分辨率:')
self.np_ratio = psg.Input(size=(25, 1), default_text='1')
self.cvs = psg.Canvas()
self.fig = plt.figure(figsize=(12, 8))
self.fig.canvas.mpl_connect('button_press_event', self.coordinate)
self.bt = psg.Button(key='draw', button_text='draw')
self.np = psg.Input(readonly=True, size=(25, 1))
self.np_start = psg.Input(readonly=True, size=(25, 1))
self.np_end = psg.Input(readonly=True, size=(25, 1))
self.np_result = psg.Input(readonly=True, size=(25, 1))
self.bt_file = psg.FileBrowse()
self.func = {
'draw': self.img_show
}
# 计算距离
def cpu_distacne(self, x1, y1, x2, y2):
distance = ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
return distance
# 坐标获取
def coordinate(self, e: MouseEvent):
print(e.dblclick, e.button)
if e.dblclick:
if e.button == MouseButton.LEFT:
self.np_start.update(value=f'start-{e.xdata:.2f}-{e.ydata:.2f}')
elif e.button == MouseButton.RIGHT:
self.np_end.update(value=f'end-{e.xdata:.2f}-{e.ydata:.2f}')
x1, y1 = self.np_start.get().split('-')[1:]
x2, y2 = self.np_end.get().split('-')[1:]
distance = self.cpu_distacne(float(x1), float(y1), float(x2), float(y2))
# print('result:{distance}')
distance = float(self.np_ratio.get()) * distance
self.np_result.update(value=f'result:{distance:.2f}')
# 控件布局
def layout(self):
layout = [
[self.np, self.bt_file, self.bt, self.tt, self.np_ratio, self.np_start, self.np_end, self.np_result],
[self.cvs]
]
return layout
# 图片显示
def img_show(self):
self.img = cv2.imread(self.value['Browse'])
self.fig.clear()
fig_img = self.fig.add_subplot(111)
fig_img.imshow(self.img)
self.tk_fig.draw()
# GUI显示
def show(self):
while True:
self.event, self.value = self.win.read()
print(self.event, self.value)
if self.event in [None]:
self.win.close()
break
if self.event in self.func:
self.func.get(self.event)()
if __name__ == '__main__':
app = MyApp()
app.show()