arjunbkool

pyqt_image_scale

Apr 8th, 2019
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.93 KB | None | 0 0
  1. # An image scale measurement tool (in pixels). Place all the images in the current folder
  2.  
  3. from PyQt5 import QtCore, QtGui, QtWidgets
  4. import math
  5. import os
  6. import sys
  7.  
  8. from PyQt5.QtCore import QEvent, Qt, pyqtSignal, pyqtSlot, QPointF, QPoint, QRectF
  9. from PyQt5.QtGui import QPixmap, QPainter, QPen, QPalette
  10. from PyQt5.QtWidgets import QMainWindow, QGraphicsScene, QGraphicsPixmapItem, QGraphicsView, QGraphicsLineItem, QFrame
  11. from PyQt5.QtWidgets import QApplication, QMessageBox
  12.  
  13.  
  14. class Ui_Window(object):
  15.     def setupUi(self, MainWindow):
  16.         MainWindow.setObjectName("MainWindow")
  17.         MainWindow.resize(1017, 639)
  18.         self.centralwidget = QtWidgets.QWidget(MainWindow)
  19.         self.centralwidget.setObjectName("centralwidget")
  20.         self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
  21.         self.gridLayout.setObjectName("gridLayout")
  22.         self.frame = QtWidgets.QFrame(self.centralwidget)
  23.         self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
  24.         self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
  25.         self.frame.setObjectName("frame")
  26.         self.gridLayout_8 = QtWidgets.QGridLayout(self.frame)
  27.         self.gridLayout_8.setObjectName("gridLayout_8")
  28.         self.pushButton = QtWidgets.QPushButton(self.frame)
  29.         self.pushButton.setObjectName("pushButton")
  30.         self.gridLayout_8.addWidget(self.pushButton, 1, 0, 1, 1)
  31.         self.listWidget = QtWidgets.QListWidget(self.frame)
  32.         self.listWidget.setObjectName("listWidget")
  33.         self.gridLayout_8.addWidget(self.listWidget, 0, 0, 1, 1)
  34.         self.gridLayout.addWidget(self.frame, 0, 0, 1, 1)
  35.         MainWindow.setCentralWidget(self.centralwidget)
  36.         self.statusbar = QtWidgets.QStatusBar(MainWindow)
  37.         self.statusbar.setObjectName("statusbar")
  38.         MainWindow.setStatusBar(self.statusbar)
  39.  
  40.         self.retranslateUi(MainWindow)
  41.         QtCore.QMetaObject.connectSlotsByName(MainWindow)
  42.  
  43.     def retranslateUi(self, MainWindow):
  44.         _translate = QtCore.QCoreApplication.translate
  45.         MainWindow.setWindowTitle(_translate("MainWindow", "Image Analyzer"))
  46.         self.pushButton.setText(_translate("MainWindow", "Update Location"))
  47.  
  48.  
  49. class Window(Ui_Window, QMainWindow):
  50.     def __init__(self):
  51.         super(Window, self).__init__()
  52.         self.setupUi(self)
  53.         self.form = ImageCheck(self)  # The view image form window where we can also measure distances
  54.         self.img_files = []  # Source image file paths
  55.         self.listWidget.itemDoubleClicked.connect(self.item_click)
  56.         self.pushButton.clicked.connect(self.update)
  57.         self.listWidget.clear()
  58.  
  59.     # To determine what happens when clicked on the text editor
  60.     def item_click(self):
  61.         path = self.listWidget.currentItem().text()  # A local Variable called "path"
  62.  
  63.         if os.path.isfile(path):
  64.             self.form.setImage(path)
  65.             self.form.show()
  66.  
  67.     def update(self):
  68.         for root, dirs, files in os.walk(os.getcwd()):
  69.             for name in files:
  70.                 if ".jpg" in name:
  71.                     self.img_files.append(os.path.join(root, name))
  72.  
  73.         self.listWidget.addItem("Current source folder has the following images")
  74.         for i in range(len(self.img_files)):
  75.             self.listWidget.addItem(self.img_files[i])  # In their order of discovery
  76.  
  77.         self.listWidget.addItem("\n")
  78.  
  79.  
  80. class Ui_ImageWindow(object):
  81.     def setupUi(self, MainWindow):
  82.         MainWindow.setObjectName("MainWindow")
  83.         MainWindow.resize(977, 928)
  84.         self.centralwidget = QtWidgets.QWidget(MainWindow)
  85.         self.centralwidget.setObjectName("centralwidget")
  86.         self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
  87.         self.gridLayout_2.setObjectName("gridLayout_2")
  88.         self.frame_1 = QtWidgets.QFrame(self.centralwidget)
  89.         self.frame_1.setFrameShape(QtWidgets.QFrame.StyledPanel)
  90.         self.frame_1.setFrameShadow(QtWidgets.QFrame.Raised)
  91.         self.frame_1.setObjectName("frame_1")
  92.         self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_1)
  93.         self.gridLayout_3.setObjectName("gridLayout_3")
  94.         self.frame_3 = QtWidgets.QFrame(self.frame_1)
  95.         self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
  96.         self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
  97.         self.frame_3.setObjectName("frame_3")
  98.         self.gridLayout = QtWidgets.QGridLayout(self.frame_3)
  99.         self.gridLayout.setObjectName("gridLayout")
  100.         self.pushButton_2 = QtWidgets.QPushButton(self.frame_3)
  101.         self.pushButton_2.setMaximumSize(QtCore.QSize(200, 30))
  102.         self.pushButton_2.setObjectName("pushButton_2")
  103.         self.gridLayout.addWidget(self.pushButton_2, 0, 3, 1, 1)
  104.         self.pushButton_1 = QtWidgets.QPushButton(self.frame_3)
  105.         self.pushButton_1.setMaximumSize(QtCore.QSize(200, 30))
  106.         self.pushButton_1.setObjectName("pushButton_1")
  107.         self.gridLayout.addWidget(self.pushButton_1, 0, 4, 1, 1)
  108.         self.lcdNumber_1 = QtWidgets.QLCDNumber(self.frame_3)
  109.         font = QtGui.QFont()
  110.         font.setFamily("Arial")
  111.         font.setPointSize(10)
  112.         font.setBold(True)
  113.         font.setWeight(75)
  114.         self.lcdNumber_1.setFont(font)
  115.         self.lcdNumber_1.setAutoFillBackground(False)
  116.         self.lcdNumber_1.setFrameShape(QtWidgets.QFrame.Box)
  117.         self.lcdNumber_1.setFrameShadow(QtWidgets.QFrame.Plain)
  118.         self.lcdNumber_1.setSmallDecimalPoint(False)
  119.         self.lcdNumber_1.setDigitCount(5)
  120.         self.lcdNumber_1.setMode(QtWidgets.QLCDNumber.Dec)
  121.         self.lcdNumber_1.setSegmentStyle(QtWidgets.QLCDNumber.Flat)
  122.         self.lcdNumber_1.setObjectName("lcdNumber_1")
  123.         self.gridLayout.addWidget(self.lcdNumber_1, 0, 1, 1, 1)
  124.         self.label_1 = QtWidgets.QLabel(self.frame_3)
  125.         self.label_1.setObjectName("label_1")
  126.         self.gridLayout.addWidget(self.label_1, 0, 0, 1, 1)
  127.         spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
  128.         self.gridLayout.addItem(spacerItem, 0, 2, 1, 1)
  129.         self.gridLayout_3.addWidget(self.frame_3, 2, 0, 1, 1)
  130.         self.frame_2 = QtWidgets.QFrame(self.frame_1)
  131.         self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
  132.         self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
  133.         self.frame_2.setObjectName("frame_2")
  134.         self.gridLayout_8 = QtWidgets.QGridLayout(self.frame_2)
  135.         self.gridLayout_8.setObjectName("gridLayout_8")
  136.         self.graphicsView = QtWidgets.QGraphicsView(self.frame_2)
  137.         self.graphicsView.setObjectName("graphicsView")
  138.         self.gridLayout_8.addWidget(self.graphicsView, 2, 0, 1, 2)
  139.         self.gridLayout_3.addWidget(self.frame_2, 1, 0, 1, 1)
  140.         self.gridLayout_2.addWidget(self.frame_1, 0, 0, 1, 1)
  141.         MainWindow.setCentralWidget(self.centralwidget)
  142.  
  143.         self.retranslateUi(MainWindow)
  144.         QtCore.QMetaObject.connectSlotsByName(MainWindow)
  145.  
  146.     def retranslateUi(self, MainWindow):
  147.         _translate = QtCore.QCoreApplication.translate
  148.         MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
  149.         self.pushButton_2.setText(_translate("MainWindow", "Cancel"))
  150.         self.pushButton_1.setText(_translate("MainWindow", "OK"))
  151.         self.label_1.setText(_translate("MainWindow", "Distance"))
  152.  
  153.  
  154. # The Image show window upon double click list widget, where we can also measure the distances
  155. class ImageCheck(Ui_ImageWindow, QMainWindow):
  156.     pointChanged = pyqtSignal(QPointF, QPointF, float)  # The value is passed from the view upon mouse button clicks
  157.  
  158.     def __init__(self, parent=None):
  159.         super(ImageCheck, self).__init__()
  160.         self.setupUi(self)
  161.  
  162.         self.crop_ratio_w = 1  # resolution difference in image when window resize
  163.         self.crop_ratio_h = 1  # resolution difference in image when window resize
  164.         self.path = None
  165.         self.pixmap = None
  166.         self.lineItem = None
  167.  
  168.         self.pushButton_1.clicked.connect(self.click1)  # OK
  169.         self.pushButton_2.clicked.connect(self.click2)  # Cancel
  170.  
  171.         # My Scene
  172.         self.scene = QGraphicsScene()
  173.         self.scene.clear()
  174.  
  175.         # My Image
  176.         self.image_item = QGraphicsPixmapItem()
  177.  
  178.         # My View
  179.         self.view = Click_QGraphicsView(self.graphicsView)
  180.         self.view.setScene(self.scene)
  181.  
  182.         # My View Initial Geometry
  183.         self.view.setGeometry(self.geometry().x() + 10, self.geometry().y() + 39, self.geometry().width() - 55,
  184.                               self.geometry().height() - 110)
  185.  
  186.         # My View Setting Scene with line
  187.         self.view.pointChanged.connect(self.line_plot)
  188.  
  189.         # My View Attributes
  190.         self.view.setBackgroundRole(QPalette.Dark)
  191.         self.view.setAlignment(Qt.AlignCenter)
  192.         self.view.setFrameShape(QFrame.NoFrame)
  193.         self.view.setRenderHint(QPainter.Antialiasing, False)
  194.  
  195.     # OK button
  196.     def click1(self):
  197.         self.close()
  198.  
  199.     # Cancel button
  200.     def click2(self):
  201.         self.close()
  202.  
  203.     # The path of the image is received here
  204.     def setImage(self, path):
  205.         self.setWindowTitle("Image Analyzer")
  206.         self.path = path
  207.         self.pixmap = QPixmap(self.path)
  208.  
  209.         # pixmap_item = self.view.scene().addPixmap(self.pixmap)
  210.         # pixmap_item.setShapeMode(QGraphicsPixmapItem.BoundingRectShape)
  211.  
  212.         self.crop_ratio_w = self.pixmap.width() / self.view.width()
  213.         self.crop_ratio_h = self.pixmap.height() / self.view.height()
  214.  
  215.         smaller_pixmap = self.pixmap.scaled(self.view.width(), self.view.height(),
  216.                                             Qt.IgnoreAspectRatio, Qt.FastTransformation)
  217.         self.image_item.setPixmap(smaller_pixmap)
  218.         self.scene.addItem(self.image_item)
  219.         self.scene.setSceneRect(0, 0, self.view.width(), self.view.height())
  220.         self.view.setGeometry(0, 0, self.view.width(), self.view.height())
  221.  
  222.         self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  223.         self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  224.         self.view.setScene(self.scene)
  225.         self.view.setSceneSize()
  226.  
  227.     # When window is resized, view size is changed and image is set again (refresh)
  228.     def resizeEvent(self, event):
  229.         self.view.setGeometry(self.geometry().x() + 10, self.geometry().y() + 39,
  230.                               self.geometry().width() - 55, self.geometry().height() - 110)
  231.         self.setImage(self.path)
  232.  
  233.         # self.view.fitInView(self.view.sceneRect(), Qt.KeepAspectRatio)
  234.         super(ImageCheck, self).resizeEvent(event)
  235.  
  236.     # The images will be closed with any line drawn and its measurement
  237.     def closeEvent(self, event):
  238.         self.lcdNumber_1.display(0.0)
  239.         self.scene.removeItem(self.lineItem)
  240.         self.close()
  241.  
  242.     # The line is plotted here
  243.     @pyqtSlot(QPointF, QPointF, float)
  244.     def line_plot(self, start, end, div):
  245.         self.scene.removeItem(self.lineItem)
  246.  
  247.         self.lineItem = QGraphicsLineItem()
  248.         self.lineItem.setPen(QPen(Qt.blue, 2.0 + div))
  249.         self.lineItem.setLine(float(start.x()), float(start.y()), float(end.x()), float(end.y()))
  250.  
  251.         x1 = start.x() * self.crop_ratio_w
  252.         x2 = end.x() * self.crop_ratio_w
  253.         y1 = start.y() * self.crop_ratio_h
  254.         y2 = end.y() * self.crop_ratio_h
  255.  
  256.         dist = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
  257.         self.lcdNumber_1.display(dist)
  258.         self.scene.addItem(self.lineItem)
  259.  
  260.  
  261. # The click associated events in view are coded here
  262. class Click_QGraphicsView(QGraphicsView):
  263.     pointChanged = pyqtSignal(QPointF, QPointF, float) # The value passed from view upon mouse button clicks
  264.  
  265.     scene_size = (0, 0)  # changing scene size
  266.     start_pos = None  # Starting position upon click
  267.     between_pos = None  # The positions in-between during mouse drag
  268.     end_pos = None  # The final position during click release
  269.     shift = False  # To check if Shift key is pressed
  270.     div = 0  # This sets the line thickness during mouse scroll
  271.  
  272.     # During shift key press for a straight line
  273.     def keyPressEvent(self, event):
  274.         if event.key() == Qt.Key_Shift:
  275.             self.shift = True
  276.  
  277.     # When shift key released
  278.     def keyReleaseEvent(self, event):
  279.         self.shift = False
  280.  
  281.     # The wheel scroll can increase or decrease thickness (only while redraw of line, including movements)
  282.     def wheelEvent(self, event):
  283.  
  284.         wheel_counter = event.angleDelta()
  285.         if wheel_counter.y() / 120 == -1:
  286.             self.div -= 0.3
  287.  
  288.         elif wheel_counter.y() / 120 == 1:
  289.             self.div += 0.3
  290.  
  291.     # When mouse button is pressed
  292.     def mousePressEvent(self, event):
  293.         self.start_pos = self.mapToScene(event.pos())
  294.         if self.start_pos.x() < 0:
  295.             self.start_pos.setX(0)
  296.         elif self.start_pos.x() > self.scene_size[0] - 1:
  297.             self.start_pos.setX(self.scene_size[0] - 1)
  298.         if self.start_pos.y() < 0:
  299.             self.start_pos.setY(0)
  300.         elif self.start_pos.y() > self.scene_size[1] - 1:
  301.             self.start_pos.setY(self.scene_size[1] - 1)
  302.  
  303.     # When mouse button is released
  304.     def mouseReleaseEvent(self, event):
  305.         self.end_pos = self.mapToScene(event.pos())
  306.         if self.end_pos.x() < 0:
  307.             self.end_pos.setX(0)
  308.         elif self.end_pos.x() > self.scene_size[0] - 1:
  309.             self.end_pos.setX(self.scene_size[0] - 1)
  310.         if self.end_pos.y() < 0:
  311.             self.end_pos.setY(0)
  312.         elif self.end_pos.y() > self.scene_size[1] - 1:
  313.             self.end_pos.setY(self.scene_size[1] - 1)
  314.  
  315.         if self.shift is True:
  316.             self.end_pos.setY(self.start_pos.y())
  317.  
  318.         self.pointChanged.emit(self.start_pos, self.end_pos, self.div)
  319.  
  320.     # When mouse is moved
  321.     def mouseMoveEvent(self, event):
  322.         self.between_pos = self.mapToScene(event.pos())
  323.         if self.between_pos.x() < 0:
  324.             self.between_pos.setX(0)
  325.         elif self.between_pos.x() > self.scene_size[0] - 1:
  326.             self.between_pos.setX(self.scene_size[0] - 1)
  327.         if self.between_pos.y() < 0:
  328.             self.between_pos.setY(0)
  329.         elif self.between_pos.y() > self.scene_size[1] - 1:
  330.             self.between_pos.setY(self.scene_size[1] - 1)
  331.  
  332.         if self.shift is True:
  333.             self.between_pos.setY(self.start_pos.y())
  334.  
  335.         self.pointChanged.emit(self.start_pos, self.between_pos, self.div)
  336.  
  337.     # To determine changing scene size for comparison, if the clicked point is outside our scope
  338.     def setSceneSize(self):
  339.         rect = self.scene().sceneRect()
  340.         self.scene_size = (rect.width(), rect.height())
  341.  
  342.  
  343. def catch_exceptions(t, val, tb):
  344.     QMessageBox.critical(None, "An exception was raised",
  345.                          "Exception type: {}".format(t))
  346.     old_hook(t, val, tb)
  347.  
  348.  
  349. old_hook = sys.excepthook
  350. sys.excepthook = catch_exceptions
  351.  
  352.  
  353. def main():
  354.     app = QApplication(sys.argv)
  355.     window = Window()
  356.     window.show()
  357.     app.exec_()
  358.  
  359.  
  360. if __name__ == '__main__': main()
Add Comment
Please, Sign In to add comment