「Python」PySide2入门| 简单拼图小工具(PySide2安装,多文件选择,layout宽高设置,显示Opencv图像等)

虽然工作上并不用经常写界面做前端,但有时候在做一些测试或写一些demo的时候需要用到简单的界面去操作和展示一些东西。所以还是需要掌握一定的界面开发工具的。C#上用Winform很方便,python上还一直不会搞。

看很多人推荐Qt,所以决定稍微学一下Qt。

python上有PyQt5和PySide2,很相似,很多函数可以互相用,只不过PySide2是Qt的亲儿子嘛,还是直接学PySide吧。

1、安装PySide2的坑

单独记这个还是有必要的,目前版本安装有个坑

pip install pyside2

安装后,按照官方例子运行的时候会报错

qt.qpa.plugin: Could not load the Qt platform plugin "windows" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: direct2d, minimal, offscreen, windows.

完全卸载python后第一个就安装pyside,也会报错。

解决方式(参考):

将 ...\Anaconda3\Lib\site-packages\PySide2\plugins\platforms\  目录下的所有文件

复制到  ...\Anaconda3\Library\plugins\platforms\   目录下,替换之前的文件即可。

目前未见其他错误

还有一点,就是设计器,pyside2安装也会带有设计器,在  ...\Anaconda3\Lib\site-packages\PySide2\  目录下

可以将该目录添加到环境变量,这样就可以直接在命令行中直接启动了。


详细代码见 https://github.com/RainkLH/ImageStitching-pyside2

2、界面编程

最终效果如下

2.1、 主界面程序框架

这是一个很简单的界面程序,可以作为通用的框架使用。其效果就是一个带有一个标签的窗口。

import sys
from PySide2.QtWidgets import *


class MainWindow(QWidget):
    # 界面窗口标题
    MainWindowTitle = "RkWindow"

    def __init__(self):
        super().__init__()
        self.setWindowTitle(self.MainWindowTitle)
        # 设置尺寸
        self.resize(100, 100)
        self.setup_ui()

    def setup_ui(self):
        # 一个标签
        self.hello_label = QLabel("Hello world!")
        # 主布局,竖向布局
        self.main_layout = QVBoxLayout()
        # 在布局中添加wiget,标签、文字框、滚动条等都是wiget
        self.main_layout.addWidget(self.hello_label)
        # 设置布局!
        self.setLayout(self.main_layout)


if __name__ == '__main__':
    # 运行界面
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

效果如图:

2.2、按钮与多文件选择

创建一个选择图片文件按钮:

self.btn_imgs = QPushButton("chose file")

按钮点击事件连接到相应的方法:

self.btn_imgs.clicked.connect(self._open_file_dialog)

多文件选择对话框:

def _open_file_dialog(self):
        dlg_file = QFileDialog()
        # 对话框标题
        dlg_file.setWindowTitle("选择图片")
        # 筛选文件类型
        dlg_file.setNameFilter("image files (*.jpg *.png *.bmp)")
        # 多文件模式
        dlg_file.setFileMode(QFileDialog.ExistingFiles)
        dlg_file.setViewMode(QFileDialog.Detail)
        if dlg_file.exec_():
            # 所选图片文件列表
            self.file_names = dlg_file.selectedFiles()
            # 拼图算法类,实例,载入图片
            self.image_stitching.set_images(self.file_names)
            # 在界面上列出所有已选中图片
            for file_name in self.file_names:
                self.tedit_selected_imgs.append(file_name)

2.3、Layout的比例和高宽

2.3.1、 比例

一个layout里面可以塞多个wiget和layout,可以通过比例来调整内部各部件的大小。

例如:

# 横向布局
layout_res_btns = QHBoxLayout()
# 各组件
self.lb_info_name_for_save = QLabel("存储名称")
self.lb_info_dir_for_save = QLabel("存储目录")
self.tedit_save_name = QLineEdit()
self.tedit_save_dir = QLineEdit()
self.btn_result_save = QPushButton("保存")
# 添加这些组件
layout_res_btns.addWidget(self.lb_info_name_for_save)
layout_res_btns.addWidget(self.tedit_save_name)
layout_res_btns.addWidget(self.lb_info_dir_for_save)
layout_res_btns.addWidget(self.tedit_save_dir)
layout_res_btns.addWidget(self.btn_result_save)
# 设置比例
layout_res_btns.setStretch(0,1)
layout_res_btns.setStretch(1,2)
layout_res_btns.setStretch(2,1)
layout_res_btns.setStretch(3,6)
layout_res_btns.setStretch(4,1)

效果如下中间区域那一部分:

2.3.2、 宽高

上图可以看出,上下的空白很多,是因为这整个layout的整体高度是自动分配的,而其里面的按钮和文本框,是默认剧中显示的,所有会有很多空白,如何让他具有固定高度呢。

修改方式是将其转换成wiget,来修改:

widget_res_btns = QWidget()
layout_res_btns = QHBoxLayout(widget_res_btns)
layout_res_btns.addWidget(...)
...
...
widget_res_btns.setFixedHeight(40)

2.4、显示Opencv(numpy)图像

python中opencv的图像实际上可以是numpy数组。

需要转换为QImage再添加到QLabel中

self.lb_img_preview = QLabel("结果预览")
img = ....# image from opencv
# 转换为QImage,注意格式,必要时使用cv2.cvtcolor()
image = QImage(img, img.shape[1], img.shape[0], img.strides[0], QImage.Format_BGR888)        
pmap = QPixmap.fromImage(image)#.scaled(lb_size,aspectMode=PySide2.QtCore.Qt.AspectRatioMode.KeepAspectRatio)
# 可以使用scaled设置缩放模式,例如KeepAspectRatio为保证长宽比的情况下自动缩放
self.lb_img_preview.setPixmap(pmap)

3、拼图算法

这里说的拼图就是最简单的拼图概念,把几张图拼成一张

原理就是先遍历所有图片文件,按照最大宽或最大高,创建一张稿纸,再依次把所有图粘贴进去。

使用opencv实现:

def stitching(self, layout):
    # 计算所需稿纸大小
    if layout == "v":
        self.h=sum([i.shape[0] for i in self.imgs])
    if layout == "h":
        self.w=sum([i.shape[1] for i in self.imgs])
    # 初始化稿纸
    color = (255, 255, 255)
    self.dst = np.array([[color for i in range(self.w)]for j in range(self.h)], dtype=np.uint8)
    # 在稿纸上粘贴每一张图片的起始位置
    index = 0
    for img in self.imgs:
        if layout == "v":
            self.dst[index:index + img.shape[0], 0:img.shape[1]] = img
            index = index + img.shape[0]
        if layout == "h":
            self.dst[0:img.shape[0], index:index + img.shape[1]] = img
            index = index + img.shape[1]
    return self.dst

4、所有源码

详细代码见 https://github.com/RainkLH/ImageStitching-pyside2

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值