Пример #1
0
    def __init__(self, window):
        super().__init__(window)
        self.left_viewer = PhotoViewer(self, window)

        # Debug styling
        self.setStyleSheet("border: 2px solid gray")
        self.left_viewer.setStyleSheet("border: 2px solid blue")
        self.left_viewer.setUpdatesEnabled(True)

        layout = QHBoxLayout(self)
        layout.addWidget(self.left_viewer)
        self.setLayout(layout)
Пример #2
0
 def __init__(self, parent=None):
     super(BPA_App, self).__init__(parent)
     self.setupUi(self)
     self.setWindowTitle("Automated Blood Stain Pattern Analysis - ABPA")
     self.viewer = PhotoViewer(self.centralwidget)
     self.viewer.setMinimumSize(500, 500)
     self.horizontalLayout.addWidget(self.viewer)
     self.actionLoad.triggered.connect(self.load_image)
     self.actionExport.triggered.connect(self.export)
     self.actionSegment_Image.triggered.connect(self.show_metrics)
     self.actionBatch_process.triggered.connect(self.show_batch_dialog)
     self.file_name = ""
     self.folder_name = ''
     self.progressBar.hide()
     self.pixmap = None
     self.result = None
     self.annotations = {}
     self.pattern_metrics = True
Пример #3
0
class DoubleViewer(QLabel):
    def __init__(self, window):
        super().__init__(window)
        self.left_viewer = PhotoViewer(self, window)

        # Debug styling
        self.setStyleSheet("border: 2px solid gray")
        self.left_viewer.setStyleSheet("border: 2px solid blue")
        self.left_viewer.setUpdatesEnabled(True)

        layout = QHBoxLayout(self)
        layout.addWidget(self.left_viewer)
        self.setLayout(layout)

    def setPhoto(self, image, image_name=None):
        self.left_viewer.setPhoto(image, image_name, self.left_viewer)
        self.update()
Пример #4
0
    def init_WINDOW(self):
        # 存储加载的图片和抽取的轮廓
        self.image = array([])
        self.cnt = array([])
        self.color_dict = get_corlor_list()
        self.choosePoints = []
        self.ocr_flag = False
        # 鼠标点击坐标和鼠标释放坐标
        self.x_clicked = 0
        self.y_clicked = 0
        self.x_released = 0
        self.y_released = 0

        self.fnmae = ''  # 加载的map
        self.baidu_api = BaiDuAPI()

        # 图片图元
        self.viewer = PhotoViewer(self)

        # UI初始化

        # 'Load image' button
        self.btnLoad = QPushButton(self)
        self.btnLoad.setText('图片加载')
        # self.btnLoad.setText('Img Load')
        self.btnLoad.clicked.connect(self.loadImage)

        self.editYearInfo = QLineEdit(self)
        self.editYearInfo.setPlaceholderText('时间')

        # Button to change from drag/pan to getting pixel info
        self.btnClickDrag = QPushButton(self)
        self.btnClickDrag.setText('点击/拖拽')
        self.btnClickDrag.setIcon(QIcon("image/dragIcon.png"))
        self.btnClickDrag.clicked.connect(self.clickDrag)

        # 点击处的信息
        self.editClickInfo = QLineEdit(self)
        self.editClickInfo.setReadOnly(True)
        self.viewer.mouse_clicked.connect(
            self.photoClicked)  # 自建的鼠标点击的传递信号连接photoClicked函数

        # 轮廓生成按钮,连接轮廓生成函数
        self.btnContour = QPushButton(self)
        self.btnContour.setText('轮廓生成')
        self.btnContour.clicked.connect(self.getContour)

        # 轮廓拖动按钮,连接轮廓拖动函数
        self.btnDrag = QPushButton(self)
        self.btnDrag.setText("轮廓拖拽")
        self.btnDrag.clicked.connect(self.dragOutline)
        self.viewer.mouse_released.connect(
            self.mouse_releasePoint)  # 自建鼠标松开信号连接了两个函数
        self.viewer.mouse_released.connect(self.contourDraged)

        # 获取轮廓信息的按钮
        self.btnContourInfo = QPushButton(self)
        self.btnContourInfo.setText("轮廓信息")
        # self.btnContourInfo.setText("Contour Info")
        self.btnContourInfo.clicked.connect(self.contour_info)

        # 显示轮廓的信息
        self.editcontourName = QLineEdit(self)
        self.editcontourName.setPlaceholderText('轮廓名称')
        # self.editcontourName.setPlaceholderText('Contour Name')

        self.editContourArea = QLineEdit(self)
        self.editContourArea.setReadOnly(True)
        self.editContourArea.setPlaceholderText("轮廓面积")
        # self.editContourArea.setPlaceholderText("Area")
        self.editContourPerimeter = QLineEdit(self)
        self.editContourPerimeter.setReadOnly(True)
        self.editContourPerimeter.setPlaceholderText("轮廓周长")
        self.editContourCentre = QLineEdit(self)
        self.editContourCentre.setPlaceholderText("轮廓重心")
        self.editContourCentre.setReadOnly(True)

        # 存储轮廓的信息
        self.btnContourSave = QPushButton(self)
        self.btnContourSave.setText("存储轮廓信息")
        # self.btnContourSave.setText("Store Profile Information")
        self.btnContourSave.clicked.connect(self.save_contour)

        # 地点识别
        self.btnSite = QPushButton(self)
        self.btnSite.setText("地点选择")
        # self.btnSite.setText("Site Selection")
        self.btnSite.clicked.connect(self.site_choose)
        self.viewer.mouse_moved.connect(self.draw_line)

        self.btnSiteInfo = QPushButton(self)
        self.btnSiteInfo.setText("地点信息")
        # self.btnSiteInfo.setText("Site Info")
        self.btnSiteInfo.clicked.connect(self.site_info)

        self.site_ContourName = QLineEdit(self)
        self.site_ContourName.setPlaceholderText("所属轮廓")
        # self.site_ContourName.setPlaceholderText("Contour Belong")

        self.editSiteName = QLineEdit(self)
        self.editSiteName.setPlaceholderText("地名")
        self.editSiteSlope = QLineEdit(self)
        self.editSiteSlope.setPlaceholderText('斜度')
        self.editSiteLenth = QLineEdit(self)
        self.editSiteLenth.setPlaceholderText('长度')
        self.editSitePos = QLineEdit(self)
        self.editSitePos.setPlaceholderText("位置")

        self.btnSiteSave = QPushButton(self)
        self.btnSiteSave.setText("存储地点信息")
        self.btnSiteSave.clicked.connect(self.save_site)

        self.setStyleSheet("QPushButton{background-color: rgb(39, 118, 148)}"
                           "QPushButton{color:white}"
                           "QPushButton:hover{color:yellow}"
                           "QPushButton:pressed{color:red;}"
                           "QPushButton{border-radius:5px}"
                           "QPushButton{border:2px groove gray}"
                           "QPushButton{border-style: outset}"
                           "QPushButton{padding:2px 4px}"
                           "QLineEdit {border:2px groove gray}"
                           "QLineEdit {border-radius:5px}"
                           "QLineEdit{padding: 2px 4px}")

        # Arrange layout
        VBlayout = QVBoxLayout(self)
        VBlayout.addWidget(self.viewer)
        HBlayout = QHBoxLayout()
        HBlayout.setAlignment(Qt.AlignLeft)
        HBlayout.addWidget(self.btnLoad)
        HBlayout.addWidget(self.editYearInfo)
        HBlayout.addWidget(self.btnClickDrag)
        HBlayout.addWidget(self.editClickInfo)
        HBlayout.addWidget(self.btnContour)
        HBlayout.addWidget(self.btnDrag)

        # 第二行信息
        HBlayoutSecond = QHBoxLayout()
        HBlayoutSecond.setAlignment(Qt.AlignLeft)
        HBlayoutSecond.addWidget(self.btnContourInfo)
        HBlayoutSecond.addWidget(self.editcontourName)
        HBlayoutSecond.addWidget(self.editContourArea)
        HBlayoutSecond.addWidget(self.editContourPerimeter)
        HBlayoutSecond.addWidget(self.editContourCentre)
        HBlayoutSecond.addWidget(self.btnContourSave)
        # 第三行信息
        HBlayoutThird = QHBoxLayout()
        HBlayoutThird.setAlignment(Qt.AlignLeft)
        HBlayoutThird.addWidget(self.btnSite)
        HBlayoutThird.addWidget(self.btnSiteInfo)
        HBlayoutThird.addWidget(self.site_ContourName)
        HBlayoutThird.addWidget(self.editSiteName)
        HBlayoutThird.addWidget(self.editSiteSlope)
        HBlayoutThird.addWidget(self.editSiteLenth)
        HBlayoutThird.addWidget(self.editSitePos)
        HBlayoutThird.addWidget(self.btnSiteSave)

        VBlayout.addLayout(HBlayout)
        VBlayout.addLayout(HBlayoutSecond)
        VBlayout.addLayout(HBlayoutThird)

        self.setGeometry(500, 300, 800, 600)
        self.setWindowTitle('历史时空')
        self.setWindowIcon(QIcon('windowIcon.png'))
        self.show()
Пример #5
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.init_WINDOW()

    def init_WINDOW(self):
        # 存储加载的图片和抽取的轮廓
        self.image = array([])
        self.cnt = array([])
        self.color_dict = get_corlor_list()
        self.choosePoints = []
        self.ocr_flag = False
        # 鼠标点击坐标和鼠标释放坐标
        self.x_clicked = 0
        self.y_clicked = 0
        self.x_released = 0
        self.y_released = 0

        self.fnmae = ''  # 加载的map
        self.baidu_api = BaiDuAPI()

        # 图片图元
        self.viewer = PhotoViewer(self)

        # UI初始化

        # 'Load image' button
        self.btnLoad = QPushButton(self)
        self.btnLoad.setText('图片加载')
        # self.btnLoad.setText('Img Load')
        self.btnLoad.clicked.connect(self.loadImage)

        self.editYearInfo = QLineEdit(self)
        self.editYearInfo.setPlaceholderText('时间')

        # Button to change from drag/pan to getting pixel info
        self.btnClickDrag = QPushButton(self)
        self.btnClickDrag.setText('点击/拖拽')
        self.btnClickDrag.setIcon(QIcon("image/dragIcon.png"))
        self.btnClickDrag.clicked.connect(self.clickDrag)

        # 点击处的信息
        self.editClickInfo = QLineEdit(self)
        self.editClickInfo.setReadOnly(True)
        self.viewer.mouse_clicked.connect(
            self.photoClicked)  # 自建的鼠标点击的传递信号连接photoClicked函数

        # 轮廓生成按钮,连接轮廓生成函数
        self.btnContour = QPushButton(self)
        self.btnContour.setText('轮廓生成')
        self.btnContour.clicked.connect(self.getContour)

        # 轮廓拖动按钮,连接轮廓拖动函数
        self.btnDrag = QPushButton(self)
        self.btnDrag.setText("轮廓拖拽")
        self.btnDrag.clicked.connect(self.dragOutline)
        self.viewer.mouse_released.connect(
            self.mouse_releasePoint)  # 自建鼠标松开信号连接了两个函数
        self.viewer.mouse_released.connect(self.contourDraged)

        # 获取轮廓信息的按钮
        self.btnContourInfo = QPushButton(self)
        self.btnContourInfo.setText("轮廓信息")
        # self.btnContourInfo.setText("Contour Info")
        self.btnContourInfo.clicked.connect(self.contour_info)

        # 显示轮廓的信息
        self.editcontourName = QLineEdit(self)
        self.editcontourName.setPlaceholderText('轮廓名称')
        # self.editcontourName.setPlaceholderText('Contour Name')

        self.editContourArea = QLineEdit(self)
        self.editContourArea.setReadOnly(True)
        self.editContourArea.setPlaceholderText("轮廓面积")
        # self.editContourArea.setPlaceholderText("Area")
        self.editContourPerimeter = QLineEdit(self)
        self.editContourPerimeter.setReadOnly(True)
        self.editContourPerimeter.setPlaceholderText("轮廓周长")
        self.editContourCentre = QLineEdit(self)
        self.editContourCentre.setPlaceholderText("轮廓重心")
        self.editContourCentre.setReadOnly(True)

        # 存储轮廓的信息
        self.btnContourSave = QPushButton(self)
        self.btnContourSave.setText("存储轮廓信息")
        # self.btnContourSave.setText("Store Profile Information")
        self.btnContourSave.clicked.connect(self.save_contour)

        # 地点识别
        self.btnSite = QPushButton(self)
        self.btnSite.setText("地点选择")
        # self.btnSite.setText("Site Selection")
        self.btnSite.clicked.connect(self.site_choose)
        self.viewer.mouse_moved.connect(self.draw_line)

        self.btnSiteInfo = QPushButton(self)
        self.btnSiteInfo.setText("地点信息")
        # self.btnSiteInfo.setText("Site Info")
        self.btnSiteInfo.clicked.connect(self.site_info)

        self.site_ContourName = QLineEdit(self)
        self.site_ContourName.setPlaceholderText("所属轮廓")
        # self.site_ContourName.setPlaceholderText("Contour Belong")

        self.editSiteName = QLineEdit(self)
        self.editSiteName.setPlaceholderText("地名")
        self.editSiteSlope = QLineEdit(self)
        self.editSiteSlope.setPlaceholderText('斜度')
        self.editSiteLenth = QLineEdit(self)
        self.editSiteLenth.setPlaceholderText('长度')
        self.editSitePos = QLineEdit(self)
        self.editSitePos.setPlaceholderText("位置")

        self.btnSiteSave = QPushButton(self)
        self.btnSiteSave.setText("存储地点信息")
        self.btnSiteSave.clicked.connect(self.save_site)

        self.setStyleSheet("QPushButton{background-color: rgb(39, 118, 148)}"
                           "QPushButton{color:white}"
                           "QPushButton:hover{color:yellow}"
                           "QPushButton:pressed{color:red;}"
                           "QPushButton{border-radius:5px}"
                           "QPushButton{border:2px groove gray}"
                           "QPushButton{border-style: outset}"
                           "QPushButton{padding:2px 4px}"
                           "QLineEdit {border:2px groove gray}"
                           "QLineEdit {border-radius:5px}"
                           "QLineEdit{padding: 2px 4px}")

        # Arrange layout
        VBlayout = QVBoxLayout(self)
        VBlayout.addWidget(self.viewer)
        HBlayout = QHBoxLayout()
        HBlayout.setAlignment(Qt.AlignLeft)
        HBlayout.addWidget(self.btnLoad)
        HBlayout.addWidget(self.editYearInfo)
        HBlayout.addWidget(self.btnClickDrag)
        HBlayout.addWidget(self.editClickInfo)
        HBlayout.addWidget(self.btnContour)
        HBlayout.addWidget(self.btnDrag)

        # 第二行信息
        HBlayoutSecond = QHBoxLayout()
        HBlayoutSecond.setAlignment(Qt.AlignLeft)
        HBlayoutSecond.addWidget(self.btnContourInfo)
        HBlayoutSecond.addWidget(self.editcontourName)
        HBlayoutSecond.addWidget(self.editContourArea)
        HBlayoutSecond.addWidget(self.editContourPerimeter)
        HBlayoutSecond.addWidget(self.editContourCentre)
        HBlayoutSecond.addWidget(self.btnContourSave)
        # 第三行信息
        HBlayoutThird = QHBoxLayout()
        HBlayoutThird.setAlignment(Qt.AlignLeft)
        HBlayoutThird.addWidget(self.btnSite)
        HBlayoutThird.addWidget(self.btnSiteInfo)
        HBlayoutThird.addWidget(self.site_ContourName)
        HBlayoutThird.addWidget(self.editSiteName)
        HBlayoutThird.addWidget(self.editSiteSlope)
        HBlayoutThird.addWidget(self.editSiteLenth)
        HBlayoutThird.addWidget(self.editSitePos)
        HBlayoutThird.addWidget(self.btnSiteSave)

        VBlayout.addLayout(HBlayout)
        VBlayout.addLayout(HBlayoutSecond)
        VBlayout.addLayout(HBlayoutThird)

        self.setGeometry(500, 300, 800, 600)
        self.setWindowTitle('历史时空')
        self.setWindowIcon(QIcon('windowIcon.png'))
        self.show()

    #     图片加载,并存入数据库
    def loadImage(self):
        fname, _ = QFileDialog.getOpenFileName(
            self, "选择地图", 'D:\\0Kind of File\\Map\\中国历史地图第三版',
            'Image files(*.jpg *.gif *.png)')
        # fi = QtCott
        # re.QFileInfo(fname) 获取fname的信息
        if not fname:
            pass
        else:
            # 从新加载图片,清空变量
            # 存储加载的图片和抽取的轮廓
            self.image = array([])
            self.cnt = array([])

            # 鼠标点击坐标和鼠标释放坐标
            self.x_clicked = 0
            self.y_clicked = 0
            self.x_released = 0
            self.y_released = 0

            self.image = cv.imdecode(fromfile(fname, dtype=uint8), -1)
            year_img = self.image[0:100, 0:500]
            cut_bila = cv.bilateralFilter(year_img,
                                          d=0,
                                          sigmaColor=75,
                                          sigmaSpace=15)
            cv.imwrite('image/year.jpg', cut_bila)
            year_str = self.baidu_api.picture2text('image/year.jpg')
            year_int = findall(r'\d+', year_str)
            if '前' in year_str:
                map_year = -int(year_int[0])
            else:
                map_year = int(year_int[0])
            myimage = open(fname, 'rb')
            map_img = myimage.read()
            mysqlConn = MySqlConn()
            self.editYearInfo.setText(str(map_year))
            # print(len(map_img))
            mysqlConn.img_insert(map_year=map_year, map_img=map_img)
            image_height, image_width, image_depth = self.image.shape
            QIm = cv.cvtColor(self.image, cv.COLOR_BGR2RGB)
            QIm = QImage(QIm.data, image_width, image_height,
                         image_width * image_depth, QImage.Format_RGB888)
            self.viewer.setPhoto(QPixmap.fromImage(QIm))
            self.viewer.fitInView()

    # 鼠标切换点击和拖拽模式
    def clickDrag(self):
        if self.viewer._contour or self.viewer._ocr:
            pass
        else:
            if self.viewer.dragMode():
                self.btnClickDrag.setIcon(QIcon("image/clickIcon.png"))
            else:
                self.btnClickDrag.setIcon(QIcon("image/dragIcon.png"))
            self.viewer.toggleDragMode()

    # 传递鼠标点击的坐标
    def photoClicked(self, pos):
        if self.viewer.dragMode() == QGraphicsView.NoDrag:
            self.editClickInfo.setText('%d, %d' % (pos.x(), pos.y()))
            self.x_clicked = pos.x()
            self.y_clicked = pos.y()

    # 获取轮廓
    def getContour(self):

        # 获取鼠标点击处的hsv值
        hsv = cv.cvtColor(self.image, cv.COLOR_BGR2HSV)

        # 使用区域的hsv均值代替某一点的hsv的值
        area_hsv = [0, 0, 0]

        for i in range(-3, 6, 3):
            for j in range(-3, 6, 3):
                area_hsv = area_hsv + hsv[self.y_clicked - i,
                                          self.x_clicked - j]
        color_hsv = area_hsv // 9
        # 判断需要提取的hsv区间
        color = False
        for key, value in self.color_dict.items():
            if color_hsv[0] >= value[0][0] and color_hsv[0] <= value[1][0] and color_hsv[1] >= value[0][1] and \
                    color_hsv[1] <= value[1][1] and color_hsv[2] >= value[0][2] and color_hsv[2] <= value[1][2]:
                color = True
                lower_HSV = value[0]
                upper_HSV = value[1]
                self.color_dict.pop(key)
                self.color_dict[key] = value
                break
        if not color:
            print("请重新选区颜色")
        else:
            # 中值滤波去除椒盐噪声
            blurImg = cv.medianBlur(self.image, 21)
            # cv.namedWindow("BlurImg",cv.WINDOW_KEEPRATIO)
            # cv.imshow("BlurImg",blurImg)
            # cv.imwrite("blur.jpg",blurImg)
            img = cv.cvtColor(blurImg, cv.COLOR_BGR2HSV)
            # 提取对应的hsv区域
            mask = cv.inRange(img, lower_HSV, upper_HSV)
            choose_color = cv.bitwise_and(img, img, mask=mask)
            result = cv.cvtColor(choose_color, cv.COLOR_HSV2BGR)
            gray = cv.cvtColor(result, cv.COLOR_BGR2GRAY)  # 图象灰度化
            # 提取图象梯度(可改进)
            gradX = cv.Sobel(gray, ddepth=cv.CV_32F, dx=1, dy=0, ksize=-1)
            gradY = cv.Sobel(gray, ddepth=cv.CV_32F, dx=0, dy=1, ksize=-1)

            # gradX = cv.Scharr(gray, cv.CV_64F, 1, 0)
            # gradY = cv.Scharr(gray, cv.CV_64F, 0, 1)
            # 保留水平和竖直梯度大的
            gradient = cv.max(gradX, gradY)
            # cv.namedWindow("Img0", cv.WINDOW_KEEPRATIO)
            # cv.imshow("Img0", gradient)
            # cv.imwrite("img0.jpg", gradient)
            gradient = cv.convertScaleAbs(gradient)
            #  寻找轮廓
            # 采用三角形法进行二值化
            # hist = cv.calcHist([gradient],[0],None,[256],[0,256])
            # plt.plot(hist)
            # plt.show()
            ret, th = cv.threshold(gradient, 0, 255,
                                   cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
            # cv.namedWindow("Img", cv.WINDOW_KEEPRATIO)
            # cv.imshow("Img", th)
            # cv.imwrite("img.jpg", th)
            kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
            # 闭运算,先腐蚀后膨胀,去除黑色小点
            closed = cv.morphologyEx(th, cv.MORPH_CLOSE, kernel, iterations=6)
            # 轮廓生成
            # cv.namedWindow("Img1", cv.WINDOW_KEEPRATIO)
            # cv.imshow("Img1", closed)
            # cv.imwrite("img1.jpg", closed)

            # OpenCV3 的findContours有三个返回值,OpenCV 4的有四个返回值
            # 应该安装opencv-python 3.*版本。
            myImage, cnts, hierarchy = cv.findContours(closed,
                                                       cv.RETR_EXTERNAL,
                                                       cv.CHAIN_APPROX_NONE)
            #print(cnts.size)
            print(type(cnts))
            print(len(cnts))
            num = 0
            con_exit = False
            for cnt in cnts:
                # pointPolygonTest检测点是否在轮廓内,
                # 若返回值为+1,表示点在多边形内部,返回值为-1,表示在多边形外部,返回值为0,表示在多边形上
                mesure = cv.pointPolygonTest(cnt,
                                             (self.x_clicked, self.y_clicked),
                                             measureDist=False)
                # 鼠标在轮廓内部
                if mesure == 1:
                    con_exit = True
                    break
                num = num + 1
            if con_exit:
                # 点在轮廓内
                self.cnt = cnts[num]  # 确定轮廓
                # print(self.cnt)
                # print(self.cnt.shape)
                #print(type(self.cnt))
                back = ones(self.image.shape, uint8) * 255
                img_contour = cv.drawContours(self.image.copy(), cnts, num,
                                              (255, 255, 255), 3)
                # img_contour1 = cv.drawContours(back, cnts, num, (0, 0, 255), 3)
                # 重新渲染
                # cv.namedWindow("Img2", cv.WINDOW_KEEPRATIO)
                # cv.imshow("Img2", img_contour1)
                # cv.imwrite("img2.jpg", img_contour1)
                image_height, image_width, image_depth = img_contour.shape
                QIm = cv.cvtColor(img_contour, cv.COLOR_BGR2RGB)
                QIm = QImage(QIm.data, image_width, image_height,
                             image_width * image_depth, QImage.Format_RGB888)
                self.viewer.setPhoto(QPixmap.fromImage(QIm))
                # 重新渲染后,图元回到拖拽模式
                self.btnClickDrag.setIcon(QIcon("image/dragIcon.png"))
            else:
                print("重新选区颜色点")

    # 轮廓拖动模式切换
    def dragOutline(self):
        if not self.viewer._contour:
            self.viewer._contour = True
            self.viewer.toggleDragMode()
            self.btnClickDrag.setIcon(QIcon("image/clickIcon.png"))
            self.btnDrag.setStyleSheet("QPushButton{color:red}")
        else:
            self.viewer._contour = False
            self.btnDrag.setStyleSheet("QPushButton{color:white}")

    # 获取鼠标松开的位置坐标
    def mouse_releasePoint(self, pos):
        self.x_released = pos.x()
        self.y_released = pos.y()

    # 轮廓拖动函数
    def contourDraged(self, pos):

        if self.viewer.dragMode(
        ) == QGraphicsView.NoDrag and self.viewer._contour == True:

            if self.cnt.any():
                for p in self.cnt:
                    if ((p[0][0] - self.x_clicked)**2 +
                        (p[0][1] - self.y_clicked)**2) <= 25:
                        p[0][0] = p[0][0] + (pos.x() - self.x_clicked) * 0.9
                        p[0][1] = p[0][1] + (pos.y() - self.y_clicked) * 0.9
                    elif ((p[0][0] - self.x_clicked)**2 +
                          (p[0][1] - self.y_clicked)**2) <= 100:
                        p[0][0] = p[0][0] + (pos.x() - self.x_clicked) * 0.7
                        p[0][1] = p[0][1] + (pos.y() - self.y_clicked) * 0.7
                    elif ((p[0][0] - self.x_clicked)**2 +
                          (p[0][1] - self.y_clicked)**2) <= 225:
                        p[0][0] = p[0][0] + (pos.x() - self.x_clicked) * 0.5
                        p[0][1] = p[0][1] + (pos.y() - self.y_clicked) * 0.5
                    elif ((p[0][0] - self.x_clicked)**2 +
                          (p[0][1] - self.y_clicked)**2) <= 400:
                        p[0][0] = p[0][0] + (pos.x() - self.x_clicked) * 0.3
                        p[0][1] = p[0][1] + (pos.y() - self.y_clicked) * 0.3
                    elif ((p[0][0] - self.x_clicked)**2 +
                          (p[0][1] - self.y_clicked)**2) <= 625:
                        p[0][0] = p[0][0] + (pos.x() - self.x_clicked) * 0.1
                        p[0][1] = p[0][1] + (pos.y() - self.y_clicked) * 0.1

                # 重新渲染图元
                img_contour = cv.drawContours(self.image.copy(), self.cnt, -1,
                                              (255, 255, 255), 3)
                image_height, image_width, image_depth = img_contour.shape
                QIm = cv.cvtColor(img_contour, cv.COLOR_BGR2RGB)
                QIm = QImage(QIm.data, image_width, image_height,
                             image_width * image_depth, QImage.Format_RGB888)
                self.viewer.setPhoto(QPixmap.fromImage(QIm))
                self.viewer.curve_mode = True
                self.viewer.toggleDragMode()  # 判断是否还处于拖拽模式

    # 获取轮廓的信息
    def contour_info(self):
        if self.cnt.any():
            ROI = zeros(self.image.shape[:2], uint8)
            proimage = self.image.copy()
            roi = cv.drawContours(ROI, [self.cnt], 0, (255, 255, 255), -1)
            x, y, w, h = cv.boundingRect(self.cnt)
            imgroi = cv.bitwise_and(proimage, proimage, mask=roi)
            site = imgroi[y:y + h, x:x + w]
            median_img = cv.medianBlur(site, 9)
            img_gray = cv.cvtColor(median_img, cv.COLOR_BGR2GRAY)
            th = cv.adaptiveThreshold(img_gray, 255,
                                      cv.ADAPTIVE_THRESH_GAUSSIAN_C,
                                      cv.THRESH_BINARY_INV, 65, 30)
            g = cv.getStructuringElement(cv.MORPH_RECT, (2, 1))
            # 形态学处理,开运算
            ersion = cv.erode(th, g, iterations=4)
            cv.imwrite('image/contour_name.jpg', ersion)
            contour_name = self.baidu_api.picture2text(
                'image/contour_name.jpg')
            self.editcontourName.setText(contour_name)
            contour_area = cv.contourArea(self.cnt)
            contour_perimeter = cv.arcLength(self.cnt, True)
            M = cv.moments(self.cnt)
            self.contour_centre = str(int(M['m10'] / M['m00'])) + ',' + str(
                int(M['m01'] / M['m00']))
            self.editContourArea.setText("%d" % (contour_area))
            self.editContourPerimeter.setText("%d" % (contour_perimeter))
            self.editContourCentre.setText(
                "%d,%d" % (int(M['m10'] / M['m00']), int(M['m01'] / M['m00'])))

    # 轮廓存储
    def save_contour(self):
        # 判断鼠标点击是否在原轮廓,
        # mesure = cv.pointPolygonTest(self.cnt, (self.x_clicked, self.y_clicked), measureDist=False)
        # # 不在,说明原轮廓处理完毕,可以将其所包含的区域填充黑色
        # if mesure != 1:
        #     # 将self.image 修改了
        # 获取色调范围列表
        self.image = cv.drawContours(self.image, [self.cnt], 0, (0, 0, 0), -1)
        contour_year = int(self.editYearInfo.text())
        contour_name = self.editcontourName.text()
        contour_points_arr = self.cnt

        print(contour_points_arr.shape)

        # narray 转换为二进制
        contour_points = dumps(contour_points_arr)
        print(len(contour_points))
        contour_area = float(self.editContourArea.text())
        contour_perimeter = float(self.editContourPerimeter.text())
        contour_centre = self.editContourCentre.text()

        mysqlConn = MySqlConn()
        mysqlConn.contour_insert(contour_year, contour_name, contour_points,
                                 contour_area, contour_perimeter,
                                 contour_centre)

    # 开启文字识别模式
    def site_choose(self):
        if not self.viewer._ocr:
            self.viewer._ocr = True
            self.viewer.toggleDragMode()
            self.x_clicked = 0
            self.y_clicked = 0
            self.x_released = 0
            self.y_released = 0
            self.btnSite.setStyleSheet("QPushButton{color:red}")
            self.ocr_flag = True
            self.btnClickDrag.setIcon(QIcon("image/clickIcon"))
        else:
            self.viewer._ocr = False
            self.btnSite.setStyleSheet("QPushButton{color:white}")
            self.ocr_flag = False

    # 文字区域画线
    def draw_line(self, pos):
        if self.viewer._ocr and self.x_clicked or self.y_clicked:
            img_line = cv.line(self.image.copy(),
                               (self.x_clicked, self.y_clicked),
                               (pos.x(), pos.y()), (0, 0, 0), 2)
            image_height, image_width, image_depth = img_line.shape
            QIm = cv.cvtColor(img_line, cv.COLOR_BGR2RGB)
            QIm = QImage(QIm.data, image_width, image_height,
                         image_width * image_depth, QImage.Format_RGB888)
            self.viewer.setPhoto(QPixmap.fromImage(QIm))
        # 终止画线
        if self.x_released or self.y_released:
            self.choosePoints = []  # 初始化存储点组
            inf = float("inf")
            if self.x_released or self.y_released:
                if (self.x_released - self.x_clicked) == 0:
                    slope = inf
                else:
                    slope = (self.y_released - self.y_clicked) / (
                        self.x_released - self.x_clicked)

                siteLenth = 0.5 * math.sqrt(
                    square(self.y_released - self.y_clicked) +
                    square(self.x_released - self.x_clicked))

                mySiteLenth = 2 * siteLenth
                self.siteLenth = ("%.2f" % mySiteLenth)
                self.editSiteLenth.setText(self.siteLenth)
                radian = math.atan(slope)
                self.siteSlope = ("%.2f" % radian)
                self.editSiteSlope.setText(self.siteSlope)
                x_bas = math.ceil(math.fabs(0.5 * siteLenth *
                                            math.sin(radian)))
                y_bas = math.ceil(math.fabs(0.5 * siteLenth *
                                            math.cos(radian)))

                if slope <= 0:
                    self.choosePoints.append([(self.x_clicked - x_bas),
                                              (self.y_clicked - y_bas)])
                    self.choosePoints.append([(self.x_clicked + x_bas),
                                              (self.y_clicked + y_bas)])
                    self.choosePoints.append([(self.x_released + x_bas),
                                              (self.y_released + y_bas)])
                    self.choosePoints.append([(self.x_released - x_bas),
                                              (self.y_released - y_bas)])
                elif slope > 0:
                    self.choosePoints.append([(self.x_clicked + x_bas),
                                              (self.y_clicked - y_bas)])
                    self.choosePoints.append([(self.x_clicked - x_bas),
                                              (self.y_clicked + y_bas)])
                    self.choosePoints.append([(self.x_released - x_bas),
                                              (self.y_released + y_bas)])
                    self.choosePoints.append([(self.x_released + x_bas),
                                              (self.y_released - y_bas)])
            self.viewer._ocr = False

    # 求地点信息
    def site_info(self):
        if self.ocr_flag:
            if self.choosePoints:
                site_contourName = self.editcontourName.text()
                self.site_ContourName.setText(site_contourName)
                points = array([self.choosePoints], int32)
                pts = points.reshape(-1, 1, 2)
                ROI = zeros(self.image.shape[:2], uint8)
                proimage = self.image.copy()
                roi = cv.drawContours(ROI, [pts], 0, (255, 255, 255), -1)
                x, y, w, h = cv.boundingRect(pts)
                imgroi = cv.bitwise_and(proimage, proimage, mask=roi)
                site = imgroi[y:y + h, x:x + w]
                cut_bila = cv.bilateralFilter(site,
                                              d=0,
                                              sigmaColor=75,
                                              sigmaSpace=15)
                self.site_centre = ((x + 0.5 * w), (y + 0.5 * h))
                cv.imwrite('image/site.jpg', cut_bila)
                siteName = self.baidu_api.picture2text('image/site.jpg')
                self.editSiteName.setText(siteName)
                self.editSitePos.setText(str(self.site_centre))

                self.viewer._ocr = True
                self.viewer.toggleDragMode()
                self.x_clicked = 0
                self.y_clicked = 0
                self.x_released = 0
                self.y_released = 0

    # 存储地点信息
    def save_site(self):
        site_year = int(self.editYearInfo.text())
        site_name = self.editSiteName.text()
        site_contour = self.site_ContourName.text()
        site_slpoe = float(self.siteSlope)
        site_lenth = float(self.siteLenth)
        site_centre = str(self.site_centre)
        mysqlConn = MySqlConn()
        mysqlConn.site_insert(site_year, site_name, site_contour, site_slpoe,
                              site_lenth, site_centre)
    def __init__(self, parent=None):
        """
        Initialize the Planetary System LRGB Aligner environment.

        :param parent: None
        """

        # The (generated) QtGui class is contained in module main_gui.py.
        QtWidgets.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Insert the photo viewer into the main GUI.
        self.ImageWindow = PhotoViewer(self)
        self.ImageWindow.setObjectName("ImageWindow")
        self.ui.verticalLayout_3.insertWidget(1, self.ImageWindow, stretch=1)

        # Connect main GUI events with method invocations.
        self.ui.buttonLoadBW.clicked.connect(self.load_bw_image)
        self.ui.buttonLoadColor.clicked.connect(self.load_color_image)
        self.ui.buttonRegistration.clicked.connect(self.compute_registration)
        self.ui.buttonComputeLRGB.clicked.connect(self.compute_lrgb)
        self.ui.buttonSetConfigParams.clicked.connect(self.edit_configuration)
        self.ui.buttonSaveRegisteredColorImage.clicked.connect(
            self.save_registered_image)
        self.ui.buttonSaveLRGB.clicked.connect(self.save_lrgb_image)
        self.ui.buttonExit.clicked.connect(self.closeEvent)

        self.ui.radioShowBW.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=0))
        self.ui.radioShowColorOrig.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=1))
        self.ui.radioShowColorRigidTransform.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=2))
        self.ui.radioShowMatches.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=3))
        self.ui.radioShowColorOptFlow.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=4))
        self.ui.radioShowLRGB.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=5))

        # Initialize the path to the home directory.
        self.current_dir = str(Path.home())

        # Initialize instance variables.
        self.image_reference = None
        self.image_reference_8bit_gray = None
        self.image_target = None
        self.image_target_8bit_gray = None
        self.image_dewarped = None
        self.image_lrgb = None
        self.pixmaps = [None, None, None, None, None, None]
        self.current_pixmap_index = None

        # Initialize status variables
        self.status_list = [
            False, False, False, False, False, False, False, False
        ]
        self.status_pointer = {
            "initialized": 0,
            "bw_loaded": 1,
            "color_loaded": 2,
            "rigid_transformed": 3,
            "optical_flow_computed": 4,
            "lrgb_computed": 5,
            "results_saved": 6
        }

        self.radio_buttons = [
            self.ui.radioShowBW,  # 0
            self.ui.radioShowColorOrig,  # 1
            self.ui.radioShowColorRigidTransform,  # 2
            self.ui.radioShowMatches,  # 3
            self.ui.radioShowColorOptFlow,  # 4
            self.ui.radioShowLRGB
        ]  # 5

        self.control_buttons = [
            self.ui.buttonSetConfigParams,  # 0
            self.ui.buttonLoadBW,  # 1
            self.ui.buttonLoadColor,  # 2
            self.ui.buttonRegistration,  # 3
            self.ui.buttonSaveRegisteredColorImage,  # 4
            self.ui.buttonComputeLRGB,  # 5
            self.ui.buttonSaveLRGB,  # 6
            self.ui.buttonExit
        ]  # 7

        self.max_button = [0, 1, 2, 4, 5, 6, 6]
        self.max_control_button = [2, 3, 4, 4, 6, 7, 8]

        self.status_busy = False

        # Create configuration object and set configuration parameters to standard values.
        self.configuration = Configuration()

        # Write the program version into the window title.
        self.setWindowTitle(self.configuration.version)

        # Start the workflow thread. It controls the computations and control of external devices.
        # By decoupling those activities from the main thread, the GUI is kept from freezing during
        # long-running activities.
        self.workflow = Workflow(self)
        sleep(self.configuration.wait_for_workflow_initialization)

        # The workflow thread sends signals during computations. Connect those signals with the
        # appropriate GUI activity.
        self.workflow.set_status_busy_signal.connect(self.set_busy)
        self.workflow.set_status_signal.connect(self.set_status)
        self.workflow.set_error_signal.connect(self.show_error_message)

        # Reset downstream status flags.
        self.set_status(0)
class LrgbAligner(QtWidgets.QMainWindow):
    """
    This class is the main class of the "Planetary System LRGB Aligner" software. It implements
    the main GUI for the communication with the user. It creates the workflow thread which controls
    all program activities asynchronously.

    """
    def __init__(self, parent=None):
        """
        Initialize the Planetary System LRGB Aligner environment.

        :param parent: None
        """

        # The (generated) QtGui class is contained in module main_gui.py.
        QtWidgets.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Insert the photo viewer into the main GUI.
        self.ImageWindow = PhotoViewer(self)
        self.ImageWindow.setObjectName("ImageWindow")
        self.ui.verticalLayout_3.insertWidget(1, self.ImageWindow, stretch=1)

        # Connect main GUI events with method invocations.
        self.ui.buttonLoadBW.clicked.connect(self.load_bw_image)
        self.ui.buttonLoadColor.clicked.connect(self.load_color_image)
        self.ui.buttonRegistration.clicked.connect(self.compute_registration)
        self.ui.buttonComputeLRGB.clicked.connect(self.compute_lrgb)
        self.ui.buttonSetConfigParams.clicked.connect(self.edit_configuration)
        self.ui.buttonSaveRegisteredColorImage.clicked.connect(
            self.save_registered_image)
        self.ui.buttonSaveLRGB.clicked.connect(self.save_lrgb_image)
        self.ui.buttonExit.clicked.connect(self.closeEvent)

        self.ui.radioShowBW.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=0))
        self.ui.radioShowColorOrig.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=1))
        self.ui.radioShowColorRigidTransform.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=2))
        self.ui.radioShowMatches.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=3))
        self.ui.radioShowColorOptFlow.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=4))
        self.ui.radioShowLRGB.clicked.connect(
            lambda: self.show_pixmap(pixmap_index=5))

        # Initialize the path to the home directory.
        self.current_dir = str(Path.home())

        # Initialize instance variables.
        self.image_reference = None
        self.image_reference_8bit_gray = None
        self.image_target = None
        self.image_target_8bit_gray = None
        self.image_dewarped = None
        self.image_lrgb = None
        self.pixmaps = [None, None, None, None, None, None]
        self.current_pixmap_index = None

        # Initialize status variables
        self.status_list = [
            False, False, False, False, False, False, False, False
        ]
        self.status_pointer = {
            "initialized": 0,
            "bw_loaded": 1,
            "color_loaded": 2,
            "rigid_transformed": 3,
            "optical_flow_computed": 4,
            "lrgb_computed": 5,
            "results_saved": 6
        }

        self.radio_buttons = [
            self.ui.radioShowBW,  # 0
            self.ui.radioShowColorOrig,  # 1
            self.ui.radioShowColorRigidTransform,  # 2
            self.ui.radioShowMatches,  # 3
            self.ui.radioShowColorOptFlow,  # 4
            self.ui.radioShowLRGB
        ]  # 5

        self.control_buttons = [
            self.ui.buttonSetConfigParams,  # 0
            self.ui.buttonLoadBW,  # 1
            self.ui.buttonLoadColor,  # 2
            self.ui.buttonRegistration,  # 3
            self.ui.buttonSaveRegisteredColorImage,  # 4
            self.ui.buttonComputeLRGB,  # 5
            self.ui.buttonSaveLRGB,  # 6
            self.ui.buttonExit
        ]  # 7

        self.max_button = [0, 1, 2, 4, 5, 6, 6]
        self.max_control_button = [2, 3, 4, 4, 6, 7, 8]

        self.status_busy = False

        # Create configuration object and set configuration parameters to standard values.
        self.configuration = Configuration()

        # Write the program version into the window title.
        self.setWindowTitle(self.configuration.version)

        # Start the workflow thread. It controls the computations and control of external devices.
        # By decoupling those activities from the main thread, the GUI is kept from freezing during
        # long-running activities.
        self.workflow = Workflow(self)
        sleep(self.configuration.wait_for_workflow_initialization)

        # The workflow thread sends signals during computations. Connect those signals with the
        # appropriate GUI activity.
        self.workflow.set_status_busy_signal.connect(self.set_busy)
        self.workflow.set_status_signal.connect(self.set_status)
        self.workflow.set_error_signal.connect(self.show_error_message)

        # Reset downstream status flags.
        self.set_status(0)

    def edit_configuration(self):
        """
        This method is invoked with the "Set configuration parameters" GUI button. Open the
        configuration editor. If the configuration is changed, reset the workflow status to
        invalidate the computations done so far.

        :return: -
        """

        editor = ConfigurationEditor(self.configuration)
        editor.exec_()
        if editor.configuration_changed:
            # If parameters have changed, a new alignment has to be computed. If both images are
            # available, set process status to 2.
            if self.current_status > 2:
                self.set_status(2)

    def load_bw_image(self):
        """
        Load the B/W reference image from a file. Keep it together with a grayscale version.

        :return: -
        """

        try:
            self.image_reference, self.image_reference_8bit_gray, self.image_reference_8bit_color = \
                self.load_image("Load B/W reference image", 0, color=False)
            self.ui.radioShowBW.setChecked(True)

            # Set the index of the image viewer to the B/W image. The pixmap with this index will
            # be loaded into the viewer with the "set_status" method.
            self.current_pixmap_index = 0
            self.set_status(1)
        except Exception as e:
            self.show_error_message(
                "Error in reading B/W image. Detailed message: " + str(e))

    def load_color_image(self):
        """
        Load the color target image from a file. Keep it together with a grayscale version.

        :return: -
        """

        try:
            self.image_target, self.image_target_8bit_gray, self.image_target_8bit_color = \
                self.load_image("Load color image to be registered", 1, color=True)
            self.ui.radioShowColorOrig.setChecked(True)
            self.current_pixmap_index = 1
            self.set_status(2)
        except Exception as e:
            self.show_error_message(
                "Error in reading color image. Detailed message: " + str(e))

    def load_image(self, message, pixmap_index, color=False):
        """
        Read an image from a file. Convert it to color mode if optional parameter is set to True.

        :param pixmap_index: Index into the list of pixel maps used to show images in GUI.
        :param color: If True, convert image to color mode. If False, convert it to grayscale.
        :return: 3-tupel with numpy arrays with image data in three versions:
            - Original depth and color / grayscale
            - 8bit grayscale
            - 8bit color
        """

        options = QtWidgets.QFileDialog.Options()
        filename = QtWidgets.QFileDialog.getOpenFileName(
            self,
            message,
            self.current_dir,
            "Images (*.tif *.tiff *.png *.jpg)",
            options=options)
        file_name = filename[0]
        if file_name == '':
            raise Exception("File dialog aborted")

        # Remember the current directory for next file dialog.
        self.current_dir = str(Path(file_name).parents[0])
        if color:
            image_read = cv2.imread(file_name, cv2.IMREAD_UNCHANGED)
            if image_read.dtype == np.uint16:
                image_read_8bit_color = (image_read / 256).astype('uint8')
            else:
                image_read_8bit_color = image_read
            image_read_8bit_gray = cv2.cvtColor(image_read_8bit_color,
                                                cv2.COLOR_BGR2GRAY)
        else:
            image_read = cv2.imread(file_name, cv2.IMREAD_ANYDEPTH)
            # If color image, convert to grayscale.
            if len(image_read.shape) == 3:
                image_read = cv2.cv2.cvtColor(image_read,
                                              cv2.COLOR_BayerRG2GRAY)
            if image_read.dtype == np.uint16:
                image_read_8bit_gray = cv2.convertScaleAbs(image_read,
                                                           alpha=(255.0 /
                                                                  65535.0))
            else:
                image_read_8bit_gray = image_read
            image_read_8bit_color = cv2.cvtColor(image_read_8bit_gray,
                                                 cv2.COLOR_GRAY2BGR)

        # Convert image into QT pixmel map, store it in list and load it into GUI viewer.
        self.pixmaps[pixmap_index] = self.create_pixmap(image_read_8bit_color)
        self.ImageWindow.setPhoto(self.pixmaps[pixmap_index])
        self.ImageWindow.fitInView()
        return image_read, image_read_8bit_gray, image_read_8bit_color

    def create_pixmap(self, cv_image):
        """
        Transform an image in OpenCV color representation (BGR) into a QT pixmap

        :param cv_image: Image array
        :return: QT QPixmap object
        """

        return QtGui.QPixmap(
            QtGui.QImage(cv_image, cv_image.shape[1], cv_image.shape[0],
                         cv_image.shape[1] * 3,
                         QtGui.QImage.Format_RGB888).rgbSwapped())

    def show_pixmap(self, pixmap_index=None):
        """
        Load a pixmap into the GUI image viewer. Adapt the view scale according to the relative
        sizes of the new and old pixmaps.

        :param pixmap_index: Index of the selected pixmap in the list. If not selected, the
                             current index is taken.
        :return: -
        """

        if pixmap_index is None:
            pixmap_index = self.current_pixmap_index

        if self.pixmaps[pixmap_index] is not None:
            self.current_pixmap_index = pixmap_index

            # Get the ratio of old pixmap and viewport sizes.
            factor_old = self.ImageWindow.fitInView(scale=False)

            # Load the new pixmap.
            self.ImageWindow.setPhoto(self.pixmaps[pixmap_index])

            # Get the ratio of new pixmap and viewport sizes.
            factor_new = self.ImageWindow.fitInView(scale=False)

            if factor_old is not None:
                # Scale the view by the relative size factors.
                factor = factor_new / factor_old
                self.ImageWindow.scale(factor, factor)

    def compute_registration(self):
        """
        If both B/W and color images are available, start the registration process.

        :return: -
        """

        if self.image_reference is not None and self.image_target is not None:
            # Tell the workflow thread to compute a new alignment.
            self.workflow.compute_alignment_flag = True

    def compute_lrgb(self):
        """
        If both B/W and color images are available, start the registration process.

        :return: -
        """

        if self.image_reference is not None and self.image_dewarped is not None:
            # Tell the workflow thread to compute a new alignment.
            self.workflow.compute_lrgb_flag = True

    def save_registered_image(self):
        """
        Open a file chooser dialog and save the de-warped image.

        :return: -
        """

        try:
            self.save_image(
                "Select location to store the registered color image",
                self.image_dewarped)
            # Udpate the status line.
            self.set_status(6)
        except:
            pass

    def save_lrgb_image(self):
        """
        Open a file chooser dialog and save the combined LRBG image.

        :return: -
        """

        try:
            self.save_image("Select location to store the combined LRGB image",
                            self.image_lrgb)
            # Udpate the status line.
            self.set_status(6)
        except:
            pass

    def save_image(self, message, image):
        """
        Open a file chooser. If a valid file name is selected, store the image to that location.

        :param message: Text to be displayed in the file chooser window.
        :param image: Image file
        :return: -
        """

        options = QtWidgets.QFileDialog.Options()
        filename = QtWidgets.QFileDialog.getSaveFileName(
            self,
            message,
            self.current_dir,
            "Images (*.tif *.tiff *.png *.jpg)",
            options=options)
        # Store image only if the chooser did not return with a cancel.
        file_name = filename[0]
        if file_name != "":
            my_file = Path(file_name)
            # Remember the current directory for next file dialog.
            self.current_dir = str(my_file.parents[0])
            if my_file.is_file():
                os.remove(str(my_file))
            if my_file.suffix == '.tif' or my_file.suffix == '.tiff':
                cv2.imwrite(file_name, image)
            elif image.dtype == np.uint16:
                image_8bit = (image / 256).astype('uint8')
                cv2.imwrite(file_name, image_8bit)
            else:
                cv2.imwrite(file_name, image)

        else:
            raise Exception("File dialog aborted")

    def set_busy(self, busy):
        """
        Set the "busy" status flag and update the status bar.

        :param busy: True, if the workflow thread is active in a computation. False, otherwise.
        :return: -
        """

        if busy:
            for button in self.control_buttons[0:7]:
                button.setEnabled(False)
        else:
            self.set_status(self.current_status)
        self.status_busy = busy
        self.set_statusbar()

    def set_status(self, status):
        """
        Enable radio buttons to show images in GUI and set the status bar according to the
        workflow status.

        :param status: Status variable
        :return: -
        """

        # Store current status.
        self.current_status = status

        # Set the current status.
        self.status_list[status] = True

        # Reset all downstream status variables to False.
        self.status_list[status +
                         1:] = [False] * (len(self.status_list) - status - 1)

        if status != 6:
            # Enable radio buttons which can be used at this point:
            for button in self.radio_buttons[:self.max_button[status]]:
                button.setEnabled(True)
            # Disable the radio buttons for showing images which do not exist at this point.
            for button in self.radio_buttons[self.max_button[status]:]:
                button.setEnabled(False)

            if not self.status_busy:
                # Enable control buttons which can be used at this point:
                for button in self.control_buttons[:self.
                                                   max_control_button[status]]:
                    button.setEnabled(True)
                # Disable the control buttons which do not make sense at this point.
                for button in self.control_buttons[
                        self.max_control_button[status]:-1]:
                    button.setEnabled(False)

        if self.configuration.skip_rigid_transformation:
            self.ui.radioShowColorRigidTransform.setEnabled(False)
            self.ui.radioShowMatches.setEnabled(False)
        if self.configuration.skip_optical_flow:
            self.ui.radioShowColorOptFlow.setEnabled(False)

        # Refresh the image viewer.
        if self.current_pixmap_index is not None:
            self.show_pixmap()

        # Update the status bar.
        self.set_statusbar()

    def set_statusbar(self):
        """
        The status bar at the bottom of the main GUI summarizes various infos on the process status.
        Read out flags to decide which infos to present. The status information is concatenated into
        a single "status_text" which eventually is written into the main GUI status bar.

        :return: -
        """

        status_text = ""

        # Tell if input images are loaded.
        if self.status_list[self.status_pointer["initialized"]]:
            status_text += "Process initialized"

        # Tell if input images are loaded.
        if self.status_list[self.status_pointer["bw_loaded"]]:
            if self.status_list[self.status_pointer["color_loaded"]]:
                status_text += ", B/W reference and color frames loaded"
            else:
                status_text += ", B/W reference frame loaded"

        # Tell if rigid transformation is done.
        if not self.configuration.skip_rigid_transformation:
            if self.status_list[self.status_pointer["rigid_transformed"]]:
                status_text += ", rigid transformation computed"
        # Tell if optical flow has been computed.
        if not self.configuration.skip_optical_flow:
            if self.status_list[self.status_pointer["optical_flow_computed"]]:
                status_text += ", images pixel-wise aligned"

        # Tell if the LRGB image is computed.
        if self.status_list[self.status_pointer["lrgb_computed"]]:
            status_text += ", LRGB image computed"

        # Tell if results are written to disk.
        if self.status_list[self.status_pointer["results_saved"]]:
            status_text += ", results written to disk"

        # Tell if the workflow thread is busy at this point.
        if self.status_busy:
            status_text += ", busy"

        # Write the complete message to the status bar.
        self.ui.statusbar.showMessage(status_text)

    def show_error_message(self, message):
        """
        Show an error message. This method is invoked from the workflow thread via the
        "set_error_signal" signal.

        :param message: Error message to be displayed
        :return: -
        """

        error_dialog = QtWidgets.QErrorMessage(self)
        error_dialog.setMinimumSize(400, 0)
        error_dialog.setWindowTitle(self.configuration.version)
        error_dialog.showMessage(message)

    def closeEvent(self, evnt):
        """
        This event is triggered when the user closes the main window by clicking on the cross in
        the window corner.

        :param evnt: event object
        :return: -
        """
        self.workflow.exiting = True
        sleep(4. * self.configuration.polling_interval)
        sys.exit(0)
Пример #8
0
    def init_WINDOW(self):
        # 存储加载的图片和抽取的轮廓
        self.image = array([])
        self.cnt = array([])
        self.color_dict = get_corlor_list()
        self.choosePoints = []
        self.ocr_flag = False

        # 存储加载的图片和抽取的轮廓——第二个图片的信息
        self.image_1 = array([])
        self.cnt_1 = array([])
        self.color_dict_1 = get_corlor_list()
        self.choosePoints_1 = []
        self.ocr_flag_1 = False


        # 鼠标点击坐标和鼠标释放坐标
        self.x_clicked = 0
        self.y_clicked = 0
        self.x_released = 0
        self.y_released = 0

        # 鼠标点击坐标和鼠标释放坐标——第二个图片的坐标
        self.x_clicked_1 = 0
        self.y_clicked_1 = 0
        self.x_released_1 = 0
        self.y_released_1 = 0

        self.fnmae = ''  # 加载的map
        self.baidu_api = BaiDuAPI()

        #第二个图片的信息
        self.fnmae_1 = ''  # 加载的map
        self.baidu_api_1 = BaiDuAPI()

        # 图片图元
        self.viewer = PhotoViewer(self)
        self.viewer_1=PhotoViewer(self)

        # UI初始化

        # 'Load image' button
        self.btnLoad = QPushButton(self)
        self.btnLoad.setText('图片加载')
        # self.btnLoad.setText('Img Load')
        self.btnLoad.clicked.connect(self.loadImage)

        # 'Load image' button ——第二个图片
        self.btnLoad_1 = QPushButton(self)
        self.btnLoad_1.setText('图片加载')
        # self.btnLoad.setText('Img Load')
        self.btnLoad_1.clicked.connect(self.loadImage_1)

        self.editYearInfo = QLineEdit(self)
        self.editYearInfo.setPlaceholderText('时间')

        self.editYearInfo_1 = QLineEdit(self)
        self.editYearInfo_1.setPlaceholderText('时间')

        # Button to change from drag/pan to getting pixel info
        self.btnClickDrag = QPushButton(self)
        self.btnClickDrag.setText('点击/拖拽')
        self.btnClickDrag.setIcon(QIcon("image/dragIcon.png"))
        self.btnClickDrag.clicked.connect(self.clickDrag)

        # Button to change from drag/pan to getting pixel info
        self.btnClickDrag_1 = QPushButton(self)
        self.btnClickDrag_1.setText('点击/拖拽')
        self.btnClickDrag_1.setIcon(QIcon("image/dragIcon.png"))
        self.btnClickDrag_1.clicked.connect(self.clickDrag_1)

        # 点击处的信息
        self.editClickInfo = QLineEdit(self)
        self.editClickInfo.setReadOnly(True)
        self.viewer.mouse_clicked.connect(self.photoClicked)  # 自建的鼠标点击的传递信号连接photoClicked函数

        # 点击处的信息——第二个图片
        self.editClickInfo_1 = QLineEdit(self)
        self.editClickInfo_1.setReadOnly(True)
        self.viewer_1.mouse_clicked.connect(self.photoClicked_1)  # 自建的鼠标点击的传递信号连接photoClicked函数

        # 轮廓生成按钮,连接轮廓生成函数
        self.btnContour = QPushButton(self)
        self.btnContour.setText('轮廓生成')
        self.btnContour.clicked.connect(self.getContour)

        # 轮廓生成按钮,连接轮廓生成函数——第二个图片
        self.btnContour_1 = QPushButton(self)
        self.btnContour_1.setText('轮廓生成')
        self.btnContour_1.clicked.connect(self.getContour_1)

        # 轮廓拖动按钮,连接轮廓拖动函数
        self.btnDrag = QPushButton(self)
        self.btnDrag.setText("轮廓拖拽")
        self.btnDrag.clicked.connect(self.dragOutline)
        self.viewer.mouse_released.connect(self.mouse_releasePoint)  # 自建鼠标松开信号连接了两个函数
        self.viewer.mouse_released.connect(self.contourDraged)


        # 轮廓拖动按钮,连接轮廓拖动函数——第二个图片
        self.btnDrag_1 = QPushButton(self)
        self.btnDrag_1.setText("轮廓拖拽")
        self.btnDrag_1.clicked.connect(self.dragOutline)
        self.viewer_1.mouse_released.connect(self.mouse_releasePoint)  # 自建鼠标松开信号连接了两个函数
        self.viewer_1.mouse_released.connect(self.contourDraged)

        # 获取轮廓信息的按钮
        self.btnContourInfo = QPushButton(self)
        self.btnContourInfo.setText("轮廓信息")
        # self.btnContourInfo.setText("Contour Info")
        self.btnContourInfo.clicked.connect(self.contour_info)

        # 获取轮廓信息的按钮——第二个图片
        self.btnContourInfo_1 = QPushButton(self)
        self.btnContourInfo_1.setText("轮廓信息")
        # self.btnContourInfo.setText("Contour Info")
        self.btnContourInfo_1.clicked.connect(self.contour_info_1)

        # 显示轮廓的信息
        self.editcontourName = QLineEdit(self)
        self.editcontourName.setPlaceholderText('轮廓名称')
        # self.editcontourName.setPlaceholderText('Contour Name')

        self.editContourArea = QLineEdit(self)
        self.editContourArea.setReadOnly(True)
        self.editContourArea.setPlaceholderText("轮廓面积")
        # self.editContourArea.setPlaceholderText("Area")
        self.editContourPerimeter = QLineEdit(self)
        self.editContourPerimeter.setReadOnly(True)
        self.editContourPerimeter.setPlaceholderText("轮廓周长")
        self.editContourCentre = QLineEdit(self)
        self.editContourCentre.setPlaceholderText("轮廓重心")
        self.editContourCentre.setReadOnly(True)

        # 显示轮廓的信息——第二个图片
        self.editcontourName_1 = QLineEdit(self)
        self.editcontourName_1.setPlaceholderText('轮廓名称')
        # self.editcontourName.setPlaceholderText('Contour Name')

        self.editContourArea_1 = QLineEdit(self)
        self.editContourArea_1.setReadOnly(True)
        self.editContourArea_1.setPlaceholderText("轮廓面积")
        # self.editContourArea.setPlaceholderText("Area")
        self.editContourPerimeter_1 = QLineEdit(self)
        self.editContourPerimeter_1.setReadOnly(True)
        self.editContourPerimeter_1.setPlaceholderText("轮廓周长")
        self.editContourCentre_1 = QLineEdit(self)
        self.editContourCentre_1.setPlaceholderText("轮廓重心")
        self.editContourCentre_1.setReadOnly(True)


        self.setStyleSheet(
            "QPushButton{background-color: rgb(39, 118, 148)}"
            "QPushButton{color:white}" "QPushButton:hover{color:yellow}" "QPushButton:pressed{color:red;}"
            "QPushButton{border-radius:5px}" "QPushButton{border:2px groove gray}" "QPushButton{border-style: outset}" "QPushButton{padding:2px 4px}"
            "QLineEdit {border:2px groove gray}" "QLineEdit {border-radius:5px}" "QLineEdit{padding: 2px 4px}"
        )

        # Arrange layout
        HBlayoutAll=QHBoxLayout(self)


        VBlayout = QVBoxLayout()
        VBlayout.addWidget(self.viewer)
        HBlayout = QHBoxLayout()
        HBlayout.setAlignment(Qt.AlignLeft)
        HBlayout.addWidget(self.btnLoad)
        HBlayout.addWidget(self.editYearInfo)
        HBlayout.addWidget(self.btnClickDrag)
        HBlayout.addWidget(self.editClickInfo)
        HBlayout.addWidget(self.btnContour)
        HBlayout.addWidget(self.btnDrag)

        # 第二行信息
        HBlayoutSecond = QHBoxLayout()
        HBlayoutSecond.setAlignment(Qt.AlignLeft)
        HBlayoutSecond.addWidget(self.btnContourInfo)
        HBlayoutSecond.addWidget(self.editcontourName)
        HBlayoutSecond.addWidget(self.editContourArea)
        HBlayoutSecond.addWidget(self.editContourPerimeter)
        HBlayoutSecond.addWidget(self.editContourCentre)


        VBlayout.addLayout(HBlayout)
        VBlayout.addLayout(HBlayoutSecond)

        #右边图片的布局
        VBlayout_1 = QVBoxLayout()
        VBlayout_1.addWidget(self.viewer_1)
        HBlayout_1 = QHBoxLayout()
        HBlayout_1.setAlignment(Qt.AlignLeft)
        HBlayout_1.addWidget(self.btnLoad_1)
        HBlayout_1.addWidget(self.editYearInfo_1)
        HBlayout_1.addWidget(self.btnClickDrag_1)
        HBlayout_1.addWidget(self.editClickInfo_1)
        HBlayout_1.addWidget(self.btnContour_1)
        HBlayout_1.addWidget(self.btnDrag_1)

        # 第二行信息
        HBlayoutSecond_1 = QHBoxLayout()
        HBlayoutSecond_1.setAlignment(Qt.AlignLeft)
        HBlayoutSecond_1.addWidget(self.btnContourInfo_1)
        HBlayoutSecond_1.addWidget(self.editcontourName_1)
        HBlayoutSecond_1.addWidget(self.editContourArea_1)
        HBlayoutSecond_1.addWidget(self.editContourPerimeter_1)
        HBlayoutSecond_1.addWidget(self.editContourCentre_1)

        VBlayout_1.addLayout(HBlayout_1)
        VBlayout_1.addLayout(HBlayoutSecond_1)

        HBlayoutAll.addLayout(VBlayout)
        HBlayoutAll.addLayout(VBlayout_1)

        self.setGeometry(500, 300, 800, 600)
        self.setWindowTitle('历史时空')
        self.setWindowIcon(QIcon('windowIcon.png'))
        self.show()
Пример #9
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.init_WINDOW()

    def init_WINDOW(self):
        # 存储加载的图片和抽取的轮廓
        self.image = array([])
        self.cnt = array([])
        self.color_dict = get_corlor_list()
        self.choosePoints = []
        self.ocr_flag = False

        # 存储加载的图片和抽取的轮廓——第二个图片的信息
        self.image_1 = array([])
        self.cnt_1 = array([])
        self.color_dict_1 = get_corlor_list()
        self.choosePoints_1 = []
        self.ocr_flag_1 = False


        # 鼠标点击坐标和鼠标释放坐标
        self.x_clicked = 0
        self.y_clicked = 0
        self.x_released = 0
        self.y_released = 0

        # 鼠标点击坐标和鼠标释放坐标——第二个图片的坐标
        self.x_clicked_1 = 0
        self.y_clicked_1 = 0
        self.x_released_1 = 0
        self.y_released_1 = 0

        self.fnmae = ''  # 加载的map
        self.baidu_api = BaiDuAPI()

        #第二个图片的信息
        self.fnmae_1 = ''  # 加载的map
        self.baidu_api_1 = BaiDuAPI()

        # 图片图元
        self.viewer = PhotoViewer(self)
        self.viewer_1=PhotoViewer(self)

        # UI初始化

        # 'Load image' button
        self.btnLoad = QPushButton(self)
        self.btnLoad.setText('图片加载')
        # self.btnLoad.setText('Img Load')
        self.btnLoad.clicked.connect(self.loadImage)

        # 'Load image' button ——第二个图片
        self.btnLoad_1 = QPushButton(self)
        self.btnLoad_1.setText('图片加载')
        # self.btnLoad.setText('Img Load')
        self.btnLoad_1.clicked.connect(self.loadImage_1)

        self.editYearInfo = QLineEdit(self)
        self.editYearInfo.setPlaceholderText('时间')

        self.editYearInfo_1 = QLineEdit(self)
        self.editYearInfo_1.setPlaceholderText('时间')

        # Button to change from drag/pan to getting pixel info
        self.btnClickDrag = QPushButton(self)
        self.btnClickDrag.setText('点击/拖拽')
        self.btnClickDrag.setIcon(QIcon("image/dragIcon.png"))
        self.btnClickDrag.clicked.connect(self.clickDrag)

        # Button to change from drag/pan to getting pixel info
        self.btnClickDrag_1 = QPushButton(self)
        self.btnClickDrag_1.setText('点击/拖拽')
        self.btnClickDrag_1.setIcon(QIcon("image/dragIcon.png"))
        self.btnClickDrag_1.clicked.connect(self.clickDrag_1)

        # 点击处的信息
        self.editClickInfo = QLineEdit(self)
        self.editClickInfo.setReadOnly(True)
        self.viewer.mouse_clicked.connect(self.photoClicked)  # 自建的鼠标点击的传递信号连接photoClicked函数

        # 点击处的信息——第二个图片
        self.editClickInfo_1 = QLineEdit(self)
        self.editClickInfo_1.setReadOnly(True)
        self.viewer_1.mouse_clicked.connect(self.photoClicked_1)  # 自建的鼠标点击的传递信号连接photoClicked函数

        # 轮廓生成按钮,连接轮廓生成函数
        self.btnContour = QPushButton(self)
        self.btnContour.setText('轮廓生成')
        self.btnContour.clicked.connect(self.getContour)

        # 轮廓生成按钮,连接轮廓生成函数——第二个图片
        self.btnContour_1 = QPushButton(self)
        self.btnContour_1.setText('轮廓生成')
        self.btnContour_1.clicked.connect(self.getContour_1)

        # 轮廓拖动按钮,连接轮廓拖动函数
        self.btnDrag = QPushButton(self)
        self.btnDrag.setText("轮廓拖拽")
        self.btnDrag.clicked.connect(self.dragOutline)
        self.viewer.mouse_released.connect(self.mouse_releasePoint)  # 自建鼠标松开信号连接了两个函数
        self.viewer.mouse_released.connect(self.contourDraged)


        # 轮廓拖动按钮,连接轮廓拖动函数——第二个图片
        self.btnDrag_1 = QPushButton(self)
        self.btnDrag_1.setText("轮廓拖拽")
        self.btnDrag_1.clicked.connect(self.dragOutline)
        self.viewer_1.mouse_released.connect(self.mouse_releasePoint)  # 自建鼠标松开信号连接了两个函数
        self.viewer_1.mouse_released.connect(self.contourDraged)

        # 获取轮廓信息的按钮
        self.btnContourInfo = QPushButton(self)
        self.btnContourInfo.setText("轮廓信息")
        # self.btnContourInfo.setText("Contour Info")
        self.btnContourInfo.clicked.connect(self.contour_info)

        # 获取轮廓信息的按钮——第二个图片
        self.btnContourInfo_1 = QPushButton(self)
        self.btnContourInfo_1.setText("轮廓信息")
        # self.btnContourInfo.setText("Contour Info")
        self.btnContourInfo_1.clicked.connect(self.contour_info_1)

        # 显示轮廓的信息
        self.editcontourName = QLineEdit(self)
        self.editcontourName.setPlaceholderText('轮廓名称')
        # self.editcontourName.setPlaceholderText('Contour Name')

        self.editContourArea = QLineEdit(self)
        self.editContourArea.setReadOnly(True)
        self.editContourArea.setPlaceholderText("轮廓面积")
        # self.editContourArea.setPlaceholderText("Area")
        self.editContourPerimeter = QLineEdit(self)
        self.editContourPerimeter.setReadOnly(True)
        self.editContourPerimeter.setPlaceholderText("轮廓周长")
        self.editContourCentre = QLineEdit(self)
        self.editContourCentre.setPlaceholderText("轮廓重心")
        self.editContourCentre.setReadOnly(True)

        # 显示轮廓的信息——第二个图片
        self.editcontourName_1 = QLineEdit(self)
        self.editcontourName_1.setPlaceholderText('轮廓名称')
        # self.editcontourName.setPlaceholderText('Contour Name')

        self.editContourArea_1 = QLineEdit(self)
        self.editContourArea_1.setReadOnly(True)
        self.editContourArea_1.setPlaceholderText("轮廓面积")
        # self.editContourArea.setPlaceholderText("Area")
        self.editContourPerimeter_1 = QLineEdit(self)
        self.editContourPerimeter_1.setReadOnly(True)
        self.editContourPerimeter_1.setPlaceholderText("轮廓周长")
        self.editContourCentre_1 = QLineEdit(self)
        self.editContourCentre_1.setPlaceholderText("轮廓重心")
        self.editContourCentre_1.setReadOnly(True)


        self.setStyleSheet(
            "QPushButton{background-color: rgb(39, 118, 148)}"
            "QPushButton{color:white}" "QPushButton:hover{color:yellow}" "QPushButton:pressed{color:red;}"
            "QPushButton{border-radius:5px}" "QPushButton{border:2px groove gray}" "QPushButton{border-style: outset}" "QPushButton{padding:2px 4px}"
            "QLineEdit {border:2px groove gray}" "QLineEdit {border-radius:5px}" "QLineEdit{padding: 2px 4px}"
        )

        # Arrange layout
        HBlayoutAll=QHBoxLayout(self)


        VBlayout = QVBoxLayout()
        VBlayout.addWidget(self.viewer)
        HBlayout = QHBoxLayout()
        HBlayout.setAlignment(Qt.AlignLeft)
        HBlayout.addWidget(self.btnLoad)
        HBlayout.addWidget(self.editYearInfo)
        HBlayout.addWidget(self.btnClickDrag)
        HBlayout.addWidget(self.editClickInfo)
        HBlayout.addWidget(self.btnContour)
        HBlayout.addWidget(self.btnDrag)

        # 第二行信息
        HBlayoutSecond = QHBoxLayout()
        HBlayoutSecond.setAlignment(Qt.AlignLeft)
        HBlayoutSecond.addWidget(self.btnContourInfo)
        HBlayoutSecond.addWidget(self.editcontourName)
        HBlayoutSecond.addWidget(self.editContourArea)
        HBlayoutSecond.addWidget(self.editContourPerimeter)
        HBlayoutSecond.addWidget(self.editContourCentre)


        VBlayout.addLayout(HBlayout)
        VBlayout.addLayout(HBlayoutSecond)

        #右边图片的布局
        VBlayout_1 = QVBoxLayout()
        VBlayout_1.addWidget(self.viewer_1)
        HBlayout_1 = QHBoxLayout()
        HBlayout_1.setAlignment(Qt.AlignLeft)
        HBlayout_1.addWidget(self.btnLoad_1)
        HBlayout_1.addWidget(self.editYearInfo_1)
        HBlayout_1.addWidget(self.btnClickDrag_1)
        HBlayout_1.addWidget(self.editClickInfo_1)
        HBlayout_1.addWidget(self.btnContour_1)
        HBlayout_1.addWidget(self.btnDrag_1)

        # 第二行信息
        HBlayoutSecond_1 = QHBoxLayout()
        HBlayoutSecond_1.setAlignment(Qt.AlignLeft)
        HBlayoutSecond_1.addWidget(self.btnContourInfo_1)
        HBlayoutSecond_1.addWidget(self.editcontourName_1)
        HBlayoutSecond_1.addWidget(self.editContourArea_1)
        HBlayoutSecond_1.addWidget(self.editContourPerimeter_1)
        HBlayoutSecond_1.addWidget(self.editContourCentre_1)

        VBlayout_1.addLayout(HBlayout_1)
        VBlayout_1.addLayout(HBlayoutSecond_1)

        HBlayoutAll.addLayout(VBlayout)
        HBlayoutAll.addLayout(VBlayout_1)

        self.setGeometry(500, 300, 800, 600)
        self.setWindowTitle('历史时空')
        self.setWindowIcon(QIcon('windowIcon.png'))
        self.show()

    #图片加载
    def loadImage(self):
            fname, _ = QFileDialog.getOpenFileName(self, "选择地图", 'D:\\0Kind of File\\Map\\中国历史地图第三版',
                                                   'Image files(*.jpg *.gif *.png)')
            # fi = QtCott
            # re.QFileInfo(fname) 获取fname的信息
            if not fname:
                pass
            else:
                # 从新加载图片,清空变量
                # 存储加载的图片和抽取的轮廓
                self.image = array([])
                self.cnt = array([])

                # 鼠标点击坐标和鼠标释放坐标
                self.x_clicked = 0
                self.y_clicked = 0
                self.x_released = 0
                self.y_released = 0

                self.image = cv.imdecode(fromfile(fname, dtype=uint8), -1)
                year_img = self.image[0:100, 0:500]
                cut_bila = cv.bilateralFilter(year_img, d=0, sigmaColor=75, sigmaSpace=15)
                cv.imwrite('image/year.jpg', cut_bila)
                year_str = self.baidu_api.picture2text('image/year.jpg')
                year_int = findall(r'\d+', year_str)
                if '前' in year_str:
                    map_year = -int(year_int[0])
                else:
                    map_year = int(year_int[0])
                myimage = open(fname, 'rb')
                map_img = myimage.read()
                #mysqlConn = MySqlConn()
                self.editYearInfo.setText(str(map_year))
                # print(len(map_img))
                #mysqlConn.img_insert(map_year=map_year, map_img=map_img)
                image_height, image_width, image_depth = self.image.shape
                QIm = cv.cvtColor(self.image, cv.COLOR_BGR2RGB)
                QIm = QImage(QIm.data, image_width, image_height, image_width * image_depth,
                             QImage.Format_RGB888)
                self.viewer.setPhoto(QPixmap.fromImage(QIm))
                self.viewer.fitInView()

    #     图片加载——第二个图片
    def loadImage_1(self):
        fname, _ = QFileDialog.getOpenFileName(self, "选择地图", 'D:\\0Kind of File\\Map\\中国历史地图第三版',
                                               'Image files(*.jpg *.gif *.png)')
        # fi = QtCott
        # re.QFileInfo(fname) 获取fname的信息
        if not fname:
            pass
        else:
            # 从新加载图片,清空变量
            # 存储加载的图片和抽取的轮廓
            self.image_1 = array([])
            self.cnt_1 = array([])

            # 鼠标点击坐标和鼠标释放坐标
            self.x_clicked_1 = 0
            self.y_clicked_1 = 0
            self.x_released_1 = 0
            self.y_released_1 = 0

            self.image_1 = cv.imdecode(fromfile(fname, dtype=uint8), -1)
            year_img = self.image_1[0:100, 0:500]
            cut_bila = cv.bilateralFilter(year_img, d=0, sigmaColor=75, sigmaSpace=15)
            cv.imwrite('image/year.jpg', cut_bila)
            year_str = self.baidu_api.picture2text('image/year.jpg')
            year_int = findall(r'\d+', year_str)
            if '前' in year_str:
                map_year = -int(year_int[0])
            else:
                map_year = int(year_int[0])
            myimage = open(fname, 'rb')
            map_img = myimage.read()
            #mysqlConn = MySqlConn()
            self.editYearInfo_1.setText(str(map_year))
            # print(len(map_img))
            #mysqlConn.img_insert(map_year=map_year, map_img=map_img)
            image_height, image_width, image_depth = self.image_1.shape
            QIm = cv.cvtColor(self.image_1, cv.COLOR_BGR2RGB)
            QIm = QImage(QIm.data, image_width, image_height, image_width * image_depth,
                         QImage.Format_RGB888)
            self.viewer_1.setPhoto(QPixmap.fromImage(QIm))
            self.viewer_1.fitInView()

    # 鼠标切换点击和拖拽模式
    def clickDrag(self):
        if self.viewer._contour or self.viewer._ocr:
            pass
        else:
            if self.viewer.dragMode():
                self.btnClickDrag.setIcon(QIcon("image/clickIcon.png"))
            else:
                self.btnClickDrag.setIcon(QIcon("image/dragIcon.png"))
            self.viewer.toggleDragMode()

    # 鼠标切换点击和拖拽模式-第二个图片
    def clickDrag_1(self):
        if self.viewer_1._contour or self.viewer_1._ocr:
            pass
        else:
            if self.viewer_1.dragMode():
                self.btnClickDrag_1.setIcon(QIcon("image/clickIcon.png"))
            else:
                self.btnClickDrag_1.setIcon(QIcon("image/dragIcon.png"))
            self.viewer_1.toggleDragMode()

    # 传递鼠标点击的坐标
    def photoClicked(self, pos):
        if self.viewer.dragMode() == QGraphicsView.NoDrag:
            self.editClickInfo.setText('%d, %d' % (pos.x(), pos.y()))
            self.x_clicked = pos.x()
            self.y_clicked = pos.y()

    # 传递鼠标点击的坐标-第二个图片
    def photoClicked_1(self, pos):
        if self.viewer_1.dragMode() == QGraphicsView.NoDrag:
            self.editClickInfo_1.setText('%d, %d' % (pos.x(), pos.y()))
            self.x_clicked_1 = pos.x()
            self.y_clicked_1 = pos.y()

    # 获取轮廓
    def getContour(self):

        # 获取鼠标点击处的hsv值
        hsv = cv.cvtColor(self.image, cv.COLOR_BGR2HSV)

        # 使用区域的hsv均值代替某一点的hsv的值
        area_hsv = [0, 0, 0]

        for i in range(-3, 6, 3):
            for j in range(-3, 6, 3):
                area_hsv = area_hsv + hsv[self.y_clicked - i, self.x_clicked - j]
        color_hsv = area_hsv // 9
        # 判断需要提取的hsv区间
        color = False
        for key, value in self.color_dict.items():
            if color_hsv[0] >= value[0][0] and color_hsv[0] <= value[1][0] and color_hsv[1] >= value[0][1] and color_hsv[1] <= value[1][1] and color_hsv[2] >= value[0][2] and color_hsv[2] <= value[1][2]:
                color = True
                lower_HSV = value[0]
                upper_HSV = value[1]
                self.color_dict.pop(key)
                self.color_dict[key] = value
                break
        if not color:
            print("请重新选区颜色")
        else:
            # 中值滤波去除椒盐噪声
            blurImg = cv.medianBlur(self.image, 21)
            img = cv.cvtColor(blurImg, cv.COLOR_BGR2HSV)
            # 提取对应的hsv区域
            mask = cv.inRange(img, lower_HSV, upper_HSV)
            choose_color = cv.bitwise_and(img, img, mask=mask)
            result = cv.cvtColor(choose_color, cv.COLOR_HSV2BGR)
            gray = cv.cvtColor(result, cv.COLOR_BGR2GRAY)  # 图象灰度化
            # 提取图象梯度(可改进)
            gradX = cv.Sobel(gray, ddepth=cv.CV_32F, dx=1, dy=0, ksize=-1)
            gradY = cv.Sobel(gray, ddepth=cv.CV_32F, dx=0, dy=1, ksize=-1)

            # gradX = cv.Scharr(gray, cv.CV_64F, 1, 0)
            # gradY = cv.Scharr(gray, cv.CV_64F, 0, 1)
            # 保留水平和竖直梯度大的
            gradient = cv.max(gradX, gradY)
            # cv.namedWindow("Img0", cv.WINDOW_KEEPRATIO)
            # cv.imshow("Img0", gradient)
            # cv.imwrite("img0.jpg", gradient)
            gradient = cv.convertScaleAbs(gradient)
            #  寻找轮廓
            # 采用三角形法进行二值化
            # hist = cv.calcHist([gradient],[0],None,[256],[0,256])
            # plt.plot(hist)
            # plt.show()
            ret, th = cv.threshold(gradient, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
            # cv.namedWindow("Img", cv.WINDOW_KEEPRATIO)
            # cv.imshow("Img", th)
            # cv.imwrite("img.jpg", th)
            kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
            # 闭运算,先腐蚀后膨胀,去除黑色小点
            closed = cv.morphologyEx(th, cv.MORPH_CLOSE, kernel, iterations=6)
            # 轮廓生成
            # cv.namedWindow("Img1", cv.WINDOW_KEEPRATIO)
            # cv.imshow("Img1", closed)
            # cv.imwrite("img1.jpg", closed)

            # OpenCV3 的findContours有三个返回值,OpenCV 4的有四个返回值
            # 应该安装opencv-python 3.*版本。
            myImage, cnts, hierarchy = cv.findContours(closed, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
            num = 0
            con_exit = False
            for cnt in cnts:
                mesure = cv.pointPolygonTest(cnt, (self.x_clicked, self.y_clicked), measureDist=False)
                if mesure == 1:
                    con_exit = True
                    break
                num = num + 1
            if con_exit:
                self.cnt = cnts[num]  # 确定轮廓

                back = ones(self.image.shape, uint8) * 255
                img_contour = cv.drawContours(self.image.copy(), cnts, num, (255, 255, 255), 3)
                # img_contour1 = cv.drawContours(back, cnts, num, (0, 0, 255), 3)
                # 重新渲染
                # cv.namedWindow("Img2", cv.WINDOW_KEEPRATIO)
                # cv.imshow("Img2", img_contour1)
                # cv.imwrite("img2.jpg", img_contour1)
                image_height, image_width, image_depth = img_contour.shape
                QIm = cv.cvtColor(img_contour, cv.COLOR_BGR2RGB)
                QIm = QImage(QIm.data, image_width, image_height, image_width * image_depth,
                             QImage.Format_RGB888)
                self.viewer.setPhoto(QPixmap.fromImage(QIm))
                # 重新渲染后,图元回到拖拽模式
                self.btnClickDrag.setIcon(QIcon("image/dragIcon.png"))
            else:
                print("重新选区颜色点")

    # 获取轮廓-第二个图片
    def getContour_1(self):

        # 获取鼠标点击处的hsv值
        hsv = cv.cvtColor(self.image_1, cv.COLOR_BGR2HSV)

        # 使用区域的hsv均值代替某一点的hsv的值
        area_hsv = [0, 0, 0]

        for i in range(-3, 6, 3):
            for j in range(-3, 6, 3):
                area_hsv = area_hsv + hsv[self.y_clicked_1 - i, self.x_clicked_1 - j]
        color_hsv = area_hsv // 9
        # 判断需要提取的hsv区间
        color = False
        for key, value in self.color_dict.items():
            if color_hsv[0] >= value[0][0] and color_hsv[0] <= value[1][0] and color_hsv[1] >= value[0][1] \
                    and color_hsv[1] <= value[1][1] and color_hsv[2] >= value[0][2] and color_hsv[2] <= value[1][2]:
                print("11111111111111")
                color = True
                lower_HSV = value[0]
                upper_HSV = value[1]
                self.color_dict.pop(key)
                self.color_dict[key] = value

                break
        print(color)
        if not color:
            print("请重新选区颜色")
        else:
            # 中值滤波去除椒盐噪声
            blurImg = cv.medianBlur(self.image_1, 21)
            img = cv.cvtColor(blurImg, cv.COLOR_BGR2HSV)
            # 提取对应的hsv区域
            mask = cv.inRange(img, lower_HSV, upper_HSV)
            choose_color = cv.bitwise_and(img, img, mask=mask)
            result = cv.cvtColor(choose_color, cv.COLOR_HSV2BGR)
            gray = cv.cvtColor(result, cv.COLOR_BGR2GRAY)  # 图象灰度化
            # 提取图象梯度(可改进)
            gradX = cv.Sobel(gray, ddepth=cv.CV_32F, dx=1, dy=0, ksize=-1)
            gradY = cv.Sobel(gray, ddepth=cv.CV_32F, dx=0, dy=1, ksize=-1)

            # gradX = cv.Scharr(gray, cv.CV_64F, 1, 0)
            # gradY = cv.Scharr(gray, cv.CV_64F, 0, 1)
            # 保留水平和竖直梯度大的
            gradient = cv.max(gradX, gradY)
            # cv.namedWindow("Img0", cv.WINDOW_KEEPRATIO)
            # cv.imshow("Img0", gradient)
            # cv.imwrite("img0.jpg", gradient)
            gradient = cv.convertScaleAbs(gradient)
            #  寻找轮廓
            # 采用三角形法进行二值化
            # hist = cv.calcHist([gradient],[0],None,[256],[0,256])
            # plt.plot(hist)
            # plt.show()
            ret, th = cv.threshold(gradient, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
            # cv.namedWindow("Img", cv.WINDOW_KEEPRATIO)
            # cv.imshow("Img", th)
            # cv.imwrite("img.jpg", th)
            kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
            # 闭运算,先腐蚀后膨胀,去除黑色小点
            closed = cv.morphologyEx(th, cv.MORPH_CLOSE, kernel, iterations=6)
            # 轮廓生成
            # cv.namedWindow("Img1", cv.WINDOW_KEEPRATIO)
            # cv.imshow("Img1", closed)
            # cv.imwrite("img1.jpg", closed)

            # OpenCV3 的findContours有三个返回值,OpenCV 4的有四个返回值
            # 应该安装opencv-python 3.*版本。
            myImage, cnts, hierarchy = cv.findContours(closed, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
            num = 0
            con_exit = False
            for cnt in cnts:
                mesure = cv.pointPolygonTest(cnt, (self.x_clicked_1, self.y_clicked_1), measureDist=False)
                if mesure == 1:
                    con_exit = True
                    break
                num = num + 1
            if con_exit:
                self.cnt_1 = cnts[num]  # 确定轮廓

                back = ones(self.image_1.shape, uint8) * 255
                img_contour = cv.drawContours(self.image_1.copy(), cnts, num, (255, 255, 255), 3)
                # img_contour1 = cv.drawContours(back, cnts, num, (0, 0, 255), 3)
                # 重新渲染
                # cv.namedWindow("Img2", cv.WINDOW_KEEPRATIO)
                # cv.imshow("Img2", img_contour1)
                # cv.imwrite("img2.jpg", img_contour1)
                image_height, image_width, image_depth = img_contour.shape
                QIm = cv.cvtColor(img_contour, cv.COLOR_BGR2RGB)
                QIm = QImage(QIm.data, image_width, image_height, image_width * image_depth,
                             QImage.Format_RGB888)
                self.viewer_1.setPhoto(QPixmap.fromImage(QIm))
                # 重新渲染后,图元回到拖拽模式
                self.btnClickDrag_1.setIcon(QIcon("image/dragIcon.png"))
            else:
                print("重新选区颜色点")

    # 轮廓拖动模式切换
    def dragOutline(self):
        if not self.viewer._contour:
            self.viewer._contour = True
            self.viewer.toggleDragMode()
            self.btnClickDrag.setIcon(QIcon("image/clickIcon.png"))
            self.btnDrag.setStyleSheet("QPushButton{color:red}")
        else:
            self.viewer._contour = False
            self.btnDrag.setStyleSheet("QPushButton{color:white}")

    # 获取鼠标松开的位置坐标
    def mouse_releasePoint(self, pos):
        self.x_released = pos.x()
        self.y_released = pos.y()

    # 轮廓拖动函数
    def contourDraged(self, pos):

        if self.viewer.dragMode() == QGraphicsView.NoDrag and self.viewer._contour == True:

            if self.cnt.any():
                for p in self.cnt:
                    if ((p[0][0] - self.x_clicked) ** 2 + (p[0][1] - self.y_clicked) ** 2) <= 25:
                        p[0][0] = p[0][0] + (pos.x() - self.x_clicked) * 0.9
                        p[0][1] = p[0][1] + (pos.y() - self.y_clicked) * 0.9
                    elif ((p[0][0] - self.x_clicked) ** 2 + (p[0][1] - self.y_clicked) ** 2) <= 100:
                        p[0][0] = p[0][0] + (pos.x() - self.x_clicked) * 0.7
                        p[0][1] = p[0][1] + (pos.y() - self.y_clicked) * 0.7
                    elif ((p[0][0] - self.x_clicked) ** 2 + (p[0][1] - self.y_clicked) ** 2) <= 225:
                        p[0][0] = p[0][0] + (pos.x() - self.x_clicked) * 0.5
                        p[0][1] = p[0][1] + (pos.y() - self.y_clicked) * 0.5
                    elif ((p[0][0] - self.x_clicked) ** 2 + (p[0][1] - self.y_clicked) ** 2) <= 400:
                        p[0][0] = p[0][0] + (pos.x() - self.x_clicked) * 0.3
                        p[0][1] = p[0][1] + (pos.y() - self.y_clicked) * 0.3
                    elif ((p[0][0] - self.x_clicked) ** 2 + (p[0][1] - self.y_clicked) ** 2) <= 625:
                        p[0][0] = p[0][0] + (pos.x() - self.x_clicked) * 0.1
                        p[0][1] = p[0][1] + (pos.y() - self.y_clicked) * 0.1

                # 重新渲染图元
                img_contour = cv.drawContours(self.image.copy(), self.cnt, -1, (255, 255, 255), 3)
                image_height, image_width, image_depth = img_contour.shape
                QIm = cv.cvtColor(img_contour, cv.COLOR_BGR2RGB)
                QIm = QImage(QIm.data, image_width, image_height, image_width * image_depth,
                             QImage.Format_RGB888)
                self.viewer.setPhoto(QPixmap.fromImage(QIm))
                self.viewer.curve_mode = True
                self.viewer.toggleDragMode()  # 判断是否还处于拖拽模式

    # 获取轮廓的信息
    def contour_info(self):
        if self.cnt.any():
            ROI = zeros(self.image.shape[:2], uint8)
            proimage = self.image.copy()
            roi = cv.drawContours(ROI, [self.cnt], 0, (255, 255, 255), -1)
            x, y, w, h = cv.boundingRect(self.cnt)
            imgroi = cv.bitwise_and(proimage, proimage, mask=roi)
            site = imgroi[y:y + h, x:x + w]
            median_img = cv.medianBlur(site, 9)
            img_gray = cv.cvtColor(median_img, cv.COLOR_BGR2GRAY)
            th = cv.adaptiveThreshold(img_gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 65, 30)
            g = cv.getStructuringElement(cv.MORPH_RECT, (2, 1))
            # 形态学处理,开运算
            ersion = cv.erode(th, g, iterations=4)
            cv.imwrite('image/contour_name.jpg', ersion)
            contour_name = self.baidu_api.picture2text('image/contour_name.jpg')
            self.editcontourName.setText(contour_name)
            contour_area = cv.contourArea(self.cnt)
            contour_perimeter = cv.arcLength(self.cnt, True)
            M = cv.moments(self.cnt)
            self.contour_centre = str(int(M['m10'] / M['m00'])) + ',' + str(int(M['m01'] / M['m00']))
            self.editContourArea.setText("%d" % (contour_area))
            self.editContourPerimeter.setText("%d" % (contour_perimeter))
            self.editContourCentre.setText("%d,%d" % (int(M['m10'] / M['m00']), int(M['m01'] / M['m00'])))

    # 获取轮廓的信息
    def contour_info_1(self):
        if self.cnt_1.any():
            ROI = zeros(self.image_1.shape[:2], uint8)
            proimage = self.image_1.copy()
            roi = cv.drawContours(ROI, [self.cnt_1], 0, (255, 255, 255), -1)
            x, y, w, h = cv.boundingRect(self.cnt_1)
            imgroi = cv.bitwise_and(proimage, proimage, mask=roi)
            site = imgroi[y:y + h, x:x + w]
            median_img = cv.medianBlur(site, 9)
            img_gray = cv.cvtColor(median_img, cv.COLOR_BGR2GRAY)
            th = cv.adaptiveThreshold(img_gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 65, 30)
            g = cv.getStructuringElement(cv.MORPH_RECT, (2, 1))
            # 形态学处理,开运算
            ersion = cv.erode(th, g, iterations=4)
            cv.imwrite('image/contour_name.jpg', ersion)
            contour_name = self.baidu_api.picture2text('image/contour_name.jpg')
            self.editcontourName_1.setText(contour_name)
            contour_area = cv.contourArea(self.cnt_1)
            contour_perimeter = cv.arcLength(self.cnt_1, True)
            M = cv.moments(self.cnt_1)
            self.contour_centre_1 = str(int(M['m10'] / M['m00'])) + ',' + str(int(M['m01'] / M['m00']))
            self.editContourArea_1.setText("%d" % (contour_area))
            self.editContourPerimeter_1.setText("%d" % (contour_perimeter))
            self.editContourCentre_1.setText("%d,%d" % (int(M['m10'] / M['m00']), int(M['m01'] / M['m00'])))

    def save_rele(self):
        contour_year = int(self.editYearInfo.text())
        contour_name = contour_year+self.editcontourName.text()

        contour_year_1 = int(self.editYearInfo_1.text())
        contour_name_1 = contour_year_1+self.editcontourName_1.text()

        mysqlConn = MySqlConn()
        mysqlConn.rele_insert(contour_year,contour_name,contour_name_1,"")
        mysqlConn.rele_insert(contour_year_1,contour_name_1,"",contour_name)
Пример #10
0
class BPA_App(QtGui.QMainWindow, main_window.Ui_MainWindow):
    def __init__(self, parent=None):
        super(BPA_App, self).__init__(parent)
        self.setupUi(self)
        self.setWindowTitle("Automated Blood Stain Pattern Analysis - ABPA")
        self.viewer = PhotoViewer(self.centralwidget)
        self.viewer.setMinimumSize(500, 500)
        self.horizontalLayout.addWidget(self.viewer)
        self.actionLoad.triggered.connect(self.load_image)
        self.actionExport.triggered.connect(self.export)
        self.actionSegment_Image.triggered.connect(self.show_metrics)
        self.actionBatch_process.triggered.connect(self.show_batch_dialog)
        self.file_name = ""
        self.folder_name = ''
        self.progressBar.hide()
        self.pixmap = None
        self.result = None
        self.annotations = {}
        self.pattern_metrics = True

    def load_image(self):
        self.file_name = QtGui.QFileDialog.getOpenFileName(
            self, 'Open file', 'c:\\', "Image files (*.jpg *.gif *.png *.tif)")
        if self.file_name:
            self.viewer.setPhoto(pixmap=QtGui.QPixmap(self.file_name))
            self.setWindowTitle("ABPA - " + self.file_name)

    def export(self):
        save_path = QtGui.QFileDialog.getSaveFileName(self, 'Open file',
                                                      'c:\\')
        if save_path:
            save_path = os.path.splitext(save_path)[0]
            self.progressBar.show()
            self.progressBar.setValue(0)
            Seg.export_stain_data(save_path, self.progressBar)
            Seg.pattern.export(save_path, self.pattern_metrics)
            self.progressBar.setValue(100)
            cv2.cvtColor(self.result, cv2.COLOR_BGR2RGB, self.result)
            cv2.drawContours(self.result, Seg.pattern.contours, -1,
                             (255, 0, 255), 3)
            for stain in Seg.pattern.stains:
                stain.annotate(self.result, self.annotations)
            cv2.imwrite(save_path + "-result.jpg", self.result)
            self.progressBar.hide()

    def show_metrics(self):
        Dialog = self.show_dialog(features_dialog.Ui_SegmenationMetrics(),
                                  self.segment_image)
        Dialog.exec_()

    def show_dialog(self, dialog, accept):
        Dialog = QtGui.QDialog()
        self.dialog = dialog
        self.dialog.setupUi(Dialog)
        self.dialog.scale_spin.setMinimum(1)
        self.dialog.scale_spin.setValue(Seg.pattern.scale)
        self.dialog.scale_spin.valueChanged.connect(self.update_scale)
        self.dialog.buttonBox.accepted.connect(accept)
        return Dialog

    def update_scale(self, value):
        Seg.pattern.scale = value

    def segment_image(self):
        if self.file_name != "":
            self.progressBar.show()
            self.progressBar.setValue(0)
            image = cv2.imread(str(self.file_name))
            orginal = cv2.imread(str(self.file_name))
            self.annotations = {
                'id': self.dialog.id.isChecked(),
                'ellipse': self.dialog.ellipse.isChecked(),
                'outline': self.dialog.outline.isChecked(),
                'center': self.dialog.center.isChecked(),
                'directionality': self.dialog.directionality.isChecked(),
                'direction_line': self.dialog.direction_line.isChecked(),
                'gamma': self.dialog.gamma.isChecked()
            }
            self.pattern_metrics = {
                'linearity': self.dialog.linearity_check.isChecked(),
                'convergence': self.dialog.convergence_check.isChecked(),
                'distribution': self.dialog.distribution_check.isChecked()
            }
            a = time.time()
            self.result = Seg.stain_segmentation(image, orginal)
            print('segment time', time.time() - a)
            result = self.result.copy()
            Seg.pattern.image = result
            Seg.pattern.name = self.file_name
            self.set_image()
            self.populate_tables()
            self.viewer.add_annotations(self.annotations, Seg.pattern)

    def set_image(self):
        height, width, byteValue = self.result.shape
        bytesPerLine = 3 * width
        cv2.cvtColor(self.result, cv2.COLOR_BGR2RGB, self.result)
        qImg = QtGui.QImage(self.result.data, width, height, bytesPerLine,
                            QtGui.QImage.Format_RGB888)
        self.pixmap = QtGui.QPixmap.fromImage(qImg)
        self.viewer.setPhoto(pixmap=self.pixmap)

    def populate_tables(self):
        self.clear_tables()
        self.populate_stain_table()
        self.populate_pattern_table()
        self.progressBar.setValue(100)
        self.progressBar.hide()

    def populate_stain_table(self):
        self.tableWidget.setColumnCount(12)
        self.tableWidget.setRowCount(len(Seg.pattern.stains))
        self.tableWidget.itemClicked.connect(self.show_stain)
        headers = "position x;position y;area px;area_mm;width ellipse;height ellipse;angle;gamma;direction;solidity;circularity;intensity"
        self.tableWidget.setHorizontalHeaderLabels(headers.split(";"))
        ids = [str(i) for i in range(0, len(Seg.pattern.stains))]
        self.tableWidget.setVerticalHeaderLabels(ids)
        j = 0
        for stain in progressbar.progressbar(Seg.pattern.stains):
            percent = (j / len(Seg.pattern.stains)) * 50
            self.progressBar.setValue(percent)
            stain_data = stain.get_summary_data()
            for i in range(1, 13):
                if stain_data[i] != None:
                    self.tableWidget.setItem(
                        j, i - 1, QtGui.QTableWidgetItem(str(stain_data[i])))
            j += 1
        self.tableWidget.show()

    def show_stain(self, item):
        position = (int(self.tableWidget.item(item.row(), 0).text()),
                    int(self.tableWidget.item(item.row(), 1).text()))
        self.viewer.add_rectangle(position[0] - 50, position[1] - 50, 100, 100)

    def populate_pattern_table(self):
        metrics = [
            "Linearity - Polyline fit", "R^2",
            "Distribution - ratio stain number to convex hull area",
            "ratio stain area to convex hull area",
            "Convergence - point of highest density",
            "box of %60 of intersections"
        ]
        self.pattern_table_widget.setColumnCount(2)
        self.pattern_table_widget.setRowCount(len(metrics))
        self.pattern_table_widget.setHorizontalHeaderLabels(
            ["Metric", "Value"])
        pattern_data = Seg.pattern.get_summary_data(self.pattern_metrics)

        for i in range(len(pattern_data)):
            self.pattern_table_widget.setItem(
                i, 0, QtGui.QTableWidgetItem(str(metrics[i])))
            self.pattern_table_widget.setItem(
                i, 1, QtGui.QTableWidgetItem(str(pattern_data[i])))

    def clear_tables(self):
        self.tableWidget.setRowCount(0)
        self.tableWidget.clear()
        self.pattern_table_widget.setRowCount(0)
        self.pattern_table_widget.clear()

    def show_batch_dialog(self):
        self.batch_dialog = batch_dialog.Ui_BatchProcessing()
        Dialog = self.show_dialog(self.batch_dialog, self.batch_process)
        self.batch_dialog.folder_path.clicked.connect(self.open_folder)
        self.batch_dialog.output_path.clicked.connect(self.output_folder)
        Dialog.exec_()

    def open_folder(self):
        folder_name = QtGui.QFileDialog.getExistingDirectory(
            None, 'Select a folder:', 'C:\\', QtGui.QFileDialog.ShowDirsOnly)
        self.batch_dialog.folder_path_edit.setText(folder_name)

    def output_folder(self):
        out_folder = QtGui.QFileDialog.getExistingDirectory(
            None, 'Select a folder:', 'C:\\', QtGui.QFileDialog.ShowDirsOnly)
        self.batch_dialog.output_path_edit.setText(out_folder)

    def batch_process(self):
        self.progressBar.show()
        self.progressBar.setValue(0)
        folder_name = self.batch_dialog.folder_path_edit.text()
        output_folder = self.batch_dialog.output_path_edit.text()
        scale = self.batch_dialog.scale_spin.value()
        if folder_name:
            Dialog = QtGui.QDialog()
            self.dialog.setupUi(Dialog)
            self.setWindowTitle("ABPA - " + folder_name)
            if folder_name[-1] != '/' and folder_name[-1] != '\\':
                folder_name += "/"
            if output_folder[-1] != '/' and output_folder[-1] != '\\':
                output_folder += "/"
            batch_process.segment_images(folder_name, output_folder, scale,
                                         self.progressBar)