diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..359bb53
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..8086a31
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..d56657a
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..2aed417
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/opencv-pyqt5-master.iml b/.idea/opencv-pyqt5-master.iml
new file mode 100644
index 0000000..d0876a7
--- /dev/null
+++ b/.idea/opencv-pyqt5-master.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/__pycache__/config.cpython-39.pyc b/__pycache__/config.cpython-39.pyc
new file mode 100644
index 0000000..942390a
Binary files /dev/null and b/__pycache__/config.cpython-39.pyc differ
diff --git a/__pycache__/flags.cpython-39.pyc b/__pycache__/flags.cpython-39.pyc
new file mode 100644
index 0000000..af50902
Binary files /dev/null and b/__pycache__/flags.cpython-39.pyc differ
diff --git a/config.py b/config.py
new file mode 100644
index 0000000..3f4fd46
--- /dev/null
+++ b/config.py
@@ -0,0 +1,108 @@
+from custom.tableWidget import *
+from custom.listWidgetItems import *
+
+
+# Implemented functions
+items = [
+ GrayingItem,
+ FilterItem,
+ EqualizeItem,
+ MorphItem,
+ GradItem,
+ ThresholdItem,
+ EdgeItem,
+ ContourItem,
+ HoughLineItem,
+ GammaItem
+
+]
+
+items1 = [
+ ImageCutItem,
+ RotateAnyItem,
+ RotateLeftItem,
+ RotateRightItem,
+ UpDownItem
+]
+
+items2 = [
+ ExposureItem,
+ ContrastItem,
+ LightItem
+]
+
+items3 = [
+ ColorTemperatureItem,
+ HueItem,
+ SaturationItem
+]
+
+items4 = [
+ HSLRedItem,
+ HSLOrangeItem,
+ HSLYellowItem,
+ HSLGreenItem,
+ HSLCyanItem,
+ HSLBlueItem,
+ HSLPurpleItem
+]
+
+items5 = [
+ PixelateItem,
+ BlurItem
+
+]
+
+items6 = [
+ CandyStyleTransformItem,
+ CompositionStyleTransformItem,
+ FeathersStyleTransformItem,
+ MuseStyleTransformItem,
+ MosaicStyleTransformItem,
+ StarryNightStyleTransformItem,
+ ScreamStyleTransformItem,
+ WaveStyleTransformItem,
+ UdnieStyleTransformItem
+]
+
+items7 = [
+ ClarityItem,
+ NoiseItem
+]
+
+tables = [
+ GrayingTableWidget,
+ FilterTabledWidget,
+ EqualizeTableWidget,
+ MorphTabledWidget,
+ GradTabledWidget,
+ ThresholdTableWidget,
+ EdgeTableWidget,
+ ContourTableWidget,
+ HoughLineTableWidget,
+ GammaITabelWidget,
+ ImageCutTableWidget,
+ RotateAnyTabelWidget,
+ RotateLeftTableWidget,
+ RotateRightTableWidget,
+ UpDownTableWidget,
+ ExposureTabelWidget,
+ ContrastTabelWidget,
+ LightTableWidget,
+ ColorTemperatureTabelWidget,
+ HueTabelWidget,
+ SaturationTabelWidget,
+ HSLRedWidget,
+ HSLOrangeWidget,
+ HSLYellowWidget,
+ HSLGreenWidget,
+ HSLCyanWidget,
+ HSLBlueWidget,
+ HSLPurpleWidget,
+ PixelateTabelWidget,
+ BlurTabelWidget,
+ StyleTransformTableWidget,
+
+
+]
+
diff --git a/custom/__pycache__/graphicsView.cpython-39.pyc b/custom/__pycache__/graphicsView.cpython-39.pyc
new file mode 100644
index 0000000..fcf1987
Binary files /dev/null and b/custom/__pycache__/graphicsView.cpython-39.pyc differ
diff --git a/custom/__pycache__/listWidgetItems.cpython-39.pyc b/custom/__pycache__/listWidgetItems.cpython-39.pyc
new file mode 100644
index 0000000..89d9f45
Binary files /dev/null and b/custom/__pycache__/listWidgetItems.cpython-39.pyc differ
diff --git a/custom/__pycache__/listWidgets.cpython-39.pyc b/custom/__pycache__/listWidgets.cpython-39.pyc
new file mode 100644
index 0000000..69b299f
Binary files /dev/null and b/custom/__pycache__/listWidgets.cpython-39.pyc differ
diff --git a/custom/__pycache__/stackedWidget.cpython-39.pyc b/custom/__pycache__/stackedWidget.cpython-39.pyc
new file mode 100644
index 0000000..5ee985b
Binary files /dev/null and b/custom/__pycache__/stackedWidget.cpython-39.pyc differ
diff --git a/custom/__pycache__/tableWidget.cpython-39.pyc b/custom/__pycache__/tableWidget.cpython-39.pyc
new file mode 100644
index 0000000..a704510
Binary files /dev/null and b/custom/__pycache__/tableWidget.cpython-39.pyc differ
diff --git a/custom/__pycache__/treeView.cpython-39.pyc b/custom/__pycache__/treeView.cpython-39.pyc
new file mode 100644
index 0000000..a616e5c
Binary files /dev/null and b/custom/__pycache__/treeView.cpython-39.pyc differ
diff --git a/custom/__pycache__/treeWidgets.cpython-39.pyc b/custom/__pycache__/treeWidgets.cpython-39.pyc
new file mode 100644
index 0000000..8042b33
Binary files /dev/null and b/custom/__pycache__/treeWidgets.cpython-39.pyc differ
diff --git a/custom/graphicsView.py b/custom/graphicsView.py
new file mode 100644
index 0000000..cbdaf35
--- /dev/null
+++ b/custom/graphicsView.py
@@ -0,0 +1,87 @@
+import cv2
+
+from PyQt5.QtGui import *
+from PyQt5.QtCore import *
+from PyQt5.QtWidgets import *
+
+
+class GraphicsView(QGraphicsView):
+ def __init__(self, parent=None):
+ super(GraphicsView, self).__init__(parent=parent)
+ self._zoom = 0
+ self._empty = True
+ self._photo = QGraphicsPixmapItem() # 创建pixmapItem对象用于显示图像
+ self._scene = QGraphicsScene(self) # 创建存储图元的容器
+ self._scene.addItem(self._photo)
+ self.setScene(self._scene)
+ self.setAlignment(Qt.AlignCenter) # 居中显示
+ self.setDragMode(QGraphicsView.ScrollHandDrag) # 设置拖动
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+ self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+ self.setMinimumSize(640, 480)
+
+ def contextMenuEvent(self, event):
+ if not self.has_photo():
+ return
+ menu = QMenu()
+ save_action = QAction('另存为', self)
+ save_action.triggered.connect(self.save_current) # 传递额外值
+ menu.addAction(save_action)
+ menu.exec(QCursor.pos())
+
+ def save_current(self):
+ file_name = QFileDialog.getSaveFileName(self, '另存为', './',
+ 'Image files(*.jpg *.gif *.png)')[0]
+ print(file_name)
+ if file_name:
+ self._photo.pixmap().save(file_name)
+
+ def get_image(self):
+ if self.has_photo():
+ return self._photo.pixmap().toImage() # 获取
+
+ def has_photo(self):
+ return not self._empty
+
+ def img_to_pixmap(self, img):
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # bgr -> rgb
+ h, w, c = img.shape # 获取图片形状
+ image = QImage(img, w, h, 3 * w, QImage.Format_RGB888)
+ return QPixmap.fromImage(image)
+
+ def update_image(self, img):
+ self._empty = False
+ self._photo.setPixmap(self.img_to_pixmap(img))
+
+ def change_image(self, img):
+ self.update_image(img)
+ self.fitInView()
+
+ def fitInView(self, scale=True):
+ rect = QRectF(self._photo.pixmap().rect())
+ if not rect.isNull():
+ self.setSceneRect(rect)
+ if self.has_photo():
+ unity = self.transform().mapRect(QRectF(0, 0, 1, 1))
+ self.scale(1 / unity.width(), 1 / unity.height())
+ viewrect = self.viewport().rect()
+ scenerect = self.transform().mapRect(rect)
+ factor = min(viewrect.width() / scenerect.width(),
+ viewrect.height() / scenerect.height())
+ self.scale(factor, factor)
+ self._zoom = 0
+
+ def wheelEvent(self, event):
+ if self.has_photo():
+ if event.angleDelta().y() > 0:
+ factor = 1.25
+ self._zoom += 1
+ else:
+ factor = 0.8
+ self._zoom -= 1
+ if self._zoom > 0:
+ self.scale(factor, factor)
+ elif self._zoom == 0:
+ self.fitInView()
+ else:
+ self._zoom = 0
diff --git a/custom/listWidgetItems.py b/custom/listWidgetItems.py
new file mode 100644
index 0000000..b148711
--- /dev/null
+++ b/custom/listWidgetItems.py
@@ -0,0 +1,912 @@
+import numpy as np
+import imutils
+from PyQt5.QtCore import QSize
+from PyQt5.QtGui import QIcon, QColor
+from PyQt5.QtWidgets import QListWidgetItem, QPushButton
+from flags import *
+import cv2
+import random
+from PIL import Image
+
+
+class MyItem(QListWidgetItem):
+ def __init__(self, name=None, parent=None):
+ super(MyItem, self).__init__(name, parent=parent)
+ self.setIcon(QIcon('icons/color.png'))
+ self.setSizeHint(QSize(60, 60)) # size
+
+ def get_params(self):
+ protected = [v for v in dir(self) if v.startswith('_') and not v.startswith('__')]
+ param = {}
+ for v in protected:
+ param[v.replace('_', '', 1)] = self.__getattribute__(v)
+ return param
+
+ def update_params(self, param):
+ for k, v in param.items():
+ if '_' + k in dir(self):
+ self.__setattr__('_' + k, v)
+
+
+class GrayingItem(MyItem):
+ def __init__(self, parent=None):
+ super(GrayingItem, self).__init__(' 灰度化 ', parent=parent)
+ self._mode = BGR2GRAY_COLOR
+
+ def __call__(self, img):
+ img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
+ img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
+ return img
+
+
+class FilterItem(MyItem):
+
+ def __init__(self, parent=None):
+ super().__init__('平滑处理', parent=parent)
+ self._ksize = 3
+ self._kind = MEAN_FILTER
+ self._sigmax = 0
+
+ def __call__(self, img):
+ if self._kind == MEAN_FILTER:
+ img = cv2.blur(img, (self._ksize, self._ksize))
+ elif self._kind == GAUSSIAN_FILTER:
+ img = cv2.GaussianBlur(img, (self._ksize, self._ksize), self._sigmax)
+ elif self._kind == MEDIAN_FILTER:
+ img = cv2.medianBlur(img, self._ksize)
+ return img
+
+
+class MorphItem(MyItem):
+ def __init__(self, parent=None):
+ super().__init__(' 形态学 ', parent=parent)
+ self._ksize = 3
+ self._op = ERODE_MORPH_OP
+ self._kshape = RECT_MORPH_SHAPE
+
+ def __call__(self, img):
+ op = MORPH_OP[self._op]
+ kshape = MORPH_SHAPE[self._kshape]
+ kernal = cv2.getStructuringElement(kshape, (self._ksize, self._ksize))
+ img = cv2.morphologyEx(img, self._op, kernal)
+ return img
+
+
+class GradItem(MyItem):
+
+ def __init__(self, parent=None):
+ super().__init__('图像梯度', parent=parent)
+ self._kind = SOBEL_GRAD
+ self._ksize = 3
+ self._dx = 1
+ self._dy = 0
+
+ def __call__(self, img):
+ if self._dx == 0 and self._dy == 0 and self._kind != LAPLACIAN_GRAD:
+ self.setBackground(QColor(255, 0, 0))
+ self.setText('图像梯度 (无效: dx与dy不同时为0)')
+ else:
+ self.setBackground(QColor(200, 200, 200))
+ self.setText('图像梯度')
+ if self._kind == SOBEL_GRAD:
+ img = cv2.Sobel(img, -1, self._dx, self._dy, self._ksize)
+ elif self._kind == SCHARR_GRAD:
+ img = cv2.Scharr(img, -1, self._dx, self._dy)
+ elif self._kind == LAPLACIAN_GRAD:
+ img = cv2.Laplacian(img, -1)
+ return img
+
+
+class ThresholdItem(MyItem):
+ def __init__(self, parent=None):
+ super().__init__('阈值处理', parent=parent)
+ self._thresh = 127
+ self._maxval = 255
+ self._method = BINARY_THRESH_METHOD
+
+ def __call__(self, img):
+ method = THRESH_METHOD[self._method]
+ img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
+ img = cv2.threshold(img, self._thresh, self._thresh, method)[1]
+ img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
+ return img
+
+
+class EdgeItem(MyItem):
+ def __init__(self, parent=None):
+ super(EdgeItem, self).__init__('边缘检测', parent=parent)
+ self._thresh1 = 20
+ self._thresh2 = 100
+
+ def __call__(self, img):
+ img = cv2.Canny(img, threshold1=self._thresh1, threshold2=self._thresh2)
+ img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
+ return img
+
+
+class ContourItem(MyItem):
+ def __init__(self, parent=None):
+ super(ContourItem, self).__init__('轮廓检测', parent=parent)
+ self._mode = TREE_CONTOUR_MODE
+ self._method = SIMPLE_CONTOUR_METHOD
+ self._bbox = NORMAL_CONTOUR
+
+ def __call__(self, img):
+ mode = CONTOUR_MODE[self._mode]
+ method = CONTOUR_METHOD[self._method]
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
+ cnts, _ = cv2.findContours(img, mode, method)
+ img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
+ if self._bbox == RECT_CONTOUR:
+ bboxs = [cv2.boundingRect(cnt) for cnt in cnts]
+ print(bboxs)
+ for x, y, w, h in bboxs:
+ img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), thickness=2)
+ elif self._bbox == MINRECT_CONTOUR:
+ bboxs = [np.int0(cv2.boxPoints(cv2.minAreaRect(cnt))) for cnt in cnts]
+ img = cv2.drawContours(img, bboxs, -1, (255, 0, 0), thickness=2)
+ elif self._bbox == MINCIRCLE_CONTOUR:
+ circles = [cv2.minEnclosingCircle(cnt) for cnt in cnts]
+ print(circles)
+ for (x, y), r in circles:
+ img = cv2.circle(img, (int(x), int(y)), int(r), (255, 0, 0), thickness=2)
+ elif self._bbox == NORMAL_CONTOUR:
+ img = cv2.drawContours(img, cnts, -1, (255, 0, 0), thickness=2)
+
+ return img
+
+
+class EqualizeItem(MyItem):
+ def __init__(self, parent=None):
+ super().__init__(' 均衡化 ', parent=parent)
+ self._blue = True
+ self._green = True
+ self._red = True
+
+ def __call__(self, img):
+ b, g, r = cv2.split(img)
+ if self._blue:
+ b = cv2.equalizeHist(b)
+ if self._green:
+ g = cv2.equalizeHist(g)
+ if self._red:
+ r = cv2.equalizeHist(r)
+ return cv2.merge((b, g, r))
+
+
+class HoughLineItem(MyItem):
+ def __init__(self, parent=None):
+ super(HoughLineItem, self).__init__('直线检测', parent=parent)
+ self._rho = 1
+ self._theta = np.pi / 180
+ self._thresh = 10
+ self._min_length = 20
+ self._max_gap = 5
+
+ def __call__(self, img):
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
+ lines = cv2.HoughLinesP(img, self._rho, self._theta, self._thresh, minLineLength=self._min_length,
+ maxLineGap=self._max_gap)
+ img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
+ if lines is None:
+ return img
+ for line in lines:
+ for x1, y1, x2, y2 in line:
+ img = cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), thickness=2)
+ return img
+
+
+class GammaItem(MyItem):
+ def __init__(self, parent=None):
+ super(GammaItem, self).__init__('伽马校正', parent=parent)
+ self._gamma = 1
+
+ def __call__(self, img):
+ gamma_table = [np.power(x / 255.0, self._gamma) * 255.0 for x in range(256)]
+ gamma_table = np.round(np.array(gamma_table)).astype(np.uint8)
+ return cv2.LUT(img, gamma_table)
+
+ # 重构:
+ # 裁剪:
+
+
+class RotateAnyItem(MyItem): # 任意旋转
+ def __init__(self, parent=None):
+ super(RotateAnyItem, self).__init__('任意旋转', parent=parent)
+ self._angle = 0
+
+ def __call__(self, img):
+ img = imutils.rotate_bound(img, self._angle)
+ return img
+
+
+class RotateLeftItem(MyItem): # 90度旋转
+ def __init__(self, parent=None):
+ super(RotateLeftItem, self).__init__('向左旋转', parent=parent)
+
+ def __call__(self, img):
+ img = imutils.rotate_bound(img, -90)
+ return img
+
+
+class RotateRightItem(MyItem): # 90度旋转
+ def __init__(self, parent=None):
+ super(RotateRightItem, self).__init__('向右旋转', parent=parent)
+
+ def __call__(self, img):
+ img = imutils.rotate_bound(img, 90)
+ return img
+
+
+class UpDownItem(MyItem):
+ def __init__(self, parent=None):
+ super(UpDownItem, self).__init__('上下翻折', parent=parent)
+
+ def __call__(self, img):
+ img = cv2.flip(img, 0)
+ return img
+
+
+# 光效
+
+
+class ExposureItem(MyItem):
+ def __init__(self, parent=None):
+ super(ExposureItem, self).__init__('曝光', parent=parent)
+ self._alpha = 1
+
+ def __call__(self, img):
+ blank = np.zeros(img.shape, img.dtype)
+ img = cv2.addWeighted(img, self._alpha, blank, 1 - self._alpha, 0)
+ return img
+
+
+class LightItem(MyItem):
+ def __init__(self, parent=None):
+ super(LightItem, self).__init__('亮度调节', parent=parent)
+ self._beta = 0
+
+ def __call__(self, img):
+ blank = np.zeros(img.shape, img.dtype)
+ img = cv2.addWeighted(img, 1, blank, 0, self._beta)
+ return img
+
+
+class ContrastItem(MyItem):
+ def __init__(self, parent=None):
+ super(ContrastItem, self).__init__('对比度调节', parent=parent)
+ self._alpha = 1
+
+ def __call__(self, img):
+ dst = np.ones(img.shape)
+ img = np.uint8(np.clip(self._alpha * (img - 127 * dst) + 127 * dst, 0, 255))
+ return img
+
+ # 色彩:
+
+
+class ColorTemperatureItem(MyItem):
+ def __init__(self, parent=None):
+ super(ColorTemperatureItem, self).__init__('色温调节', parent=parent)
+ self._n = 50
+
+ def __call__(self, img):
+ level = self._n / 2
+ # src = img.clone()
+ info = img.shape
+ row = info[0]
+ col = info[1]
+ for i in range(0, row):
+ for j in range(0, col):
+ (r, b, g) = img[i, j]
+ rr = r - level
+ bb = b - level
+ gg = g + level
+ if rr > 255:
+ rr = 255
+ elif rr < 0:
+ rr = 0
+ if bb > 255:
+ bb = 255
+ elif bb < 0:
+ bb = 0
+ if gg > 255:
+ gg = 255
+ elif gg < 0:
+ gg = 0
+ img[i, j] = (rr, bb, gg)
+ return img
+
+
+class HueItem(MyItem):
+ def __init__(self, parent=None):
+ super(HueItem, self).__init__('色调调节', parent=parent)
+ self._n = 50
+
+ def __call__(self, img):
+ level = self._n / 2
+ # src = img.clone()
+ info = img.shape
+ row = info[0]
+ col = info[1]
+ for i in range(0, row):
+ for j in range(0, col):
+ (r, b, g) = img[i, j]
+ rr = r + level
+ bb = b - level
+ gg = g + level
+ if rr > 255:
+ rr = 255
+ elif rr < 0:
+ rr = 0
+ if bb > 255:
+ bb = 255
+ elif bb < 0:
+ bb = 0
+ if gg > 255:
+ gg = 255
+ elif gg < 0:
+ gg = 0
+ img[i, j] = (rr, bb, gg)
+ return img
+
+
+class SaturationItem(MyItem):
+ def __init__(self, parent=None):
+ super(SaturationItem, self).__init__('饱和度调节', parent=parent)
+ self._x = 0
+
+ def __call__(self, img):
+ img_t = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
+ # 获取hsv
+ h, s, v = cv2.split(img_t)
+ # 增加饱和度 饱和度越低,越接近灰度图像
+ s1 = np.clip(cv2.add(s, self._x), 0, 255)
+ img = np.uint8(cv2.merge((h, s1, v)))
+ img = cv2.cvtColor(img, cv2.COLOR_HSV2BGR)
+ return img
+
+ # HSL:
+
+
+class HSLRedItem(MyItem):
+ def __init__(self, parent=None):
+ super(HSLRedItem, self).__init__('红色', parent=parent)
+ self._red_param_s = 1.0
+ self._red_param_v = 1.0
+
+ def __call__(self, img):
+ img_hsl = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
+ info = img.shape
+ height = info[0]
+ width = info[1]
+ value1 = self._red_param_v - 1.0
+ value2 = self._red_param_s - 1.0
+ for m in range(height):
+ for w in range(width):
+ h, s, v = img_hsl[m, w]
+ b, g, r = img[m, w]
+ tag = abs((int(b) - int(g)) * (int(g) - int(r)))
+ if 43 < s < 255 and 46 < v < 255 and tag > 1600:
+ if 0 < h < 10 or 156 < h < 180:
+ b = (b + (b - v) * value2)
+ g = (g + (g - v) * value2)
+ r = (r + (r - v) * value2)
+ b = b + value1 * (255 - b)
+ g = g + value1 * (255 - g)
+ r = r + value1 * (255 - r)
+
+ img[m, w] = [b, g, r]
+
+ return img
+
+
+class HSLOrangeItem(MyItem):
+ def __init__(self, parent=None):
+ super(HSLOrangeItem, self).__init__('橙色', parent=parent)
+ self._orange_param_s = 1.0
+ self._orange_param_v = 1.0
+
+ def __call__(self, img):
+ img_hsl = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
+ info = img.shape
+ height = info[0]
+ width = info[1]
+ value1 = self._orange_param_v - 1.0
+ value2 = self._orange_param_s - 1.0
+ for m in range(height):
+ for w in range(width):
+ h, s, v = img_hsl[m, w]
+ b, g, r = img[m, w]
+ tag = abs((int(b) - int(g)) * (int(g) - int(r)))
+ if 43 < s < 255 and 46 < v < 255 and tag > 1600:
+ if 11 < h < 25:
+ b = (b + (b - v) * value2)
+ g = (g + (g - v) * value2)
+ r = (r + (r - v) * value2)
+ b = b + value1 * (255 - b)
+ g = g + value1 * (255 - g)
+ r = r + value1 * (255 - r)
+
+ img[m, w] = [b, g, r]
+
+ return img
+
+
+class HSLYellowItem(MyItem):
+ def __init__(self, parent=None):
+ super(HSLYellowItem, self).__init__('黄色', parent=parent)
+ self._yellow_param_s = 1.0
+ self._yellow_param_v = 1.0
+
+ def __call__(self, img):
+ img_hsl = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
+ info = img.shape
+ height = info[0]
+ width = info[1]
+ value1 = self._yellow_param_v - 1.0
+ value2 = self._yellow_param_s - 1.0
+ for m in range(height):
+ for w in range(width):
+ h, s, v = img_hsl[m, w]
+ b, g, r = img[m, w]
+ tag = abs((int(b) - int(g)) * (int(g) - int(r)))
+ if 43 < s < 255 and 46 < v < 255 and tag > 1600:
+ if 26 < h < 34:
+ b = (b + (b - v) * value2)
+ g = (g + (g - v) * value2)
+ r = (r + (r - v) * value2)
+ b = b + value1 * (255 - b)
+ g = g + value1 * (255 - g)
+ r = r + value1 * (255 - r)
+
+ img[m, w] = [b, g, r]
+
+ return img
+
+
+class HSLGreenItem(MyItem):
+ def __init__(self, parent=None):
+ super(HSLGreenItem, self).__init__('绿色', parent=parent)
+ self._green_param_s = 1.0
+ self._green_param_v = 1.0
+
+ def __call__(self, img):
+ img_hsl = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
+ info = img.shape
+ height = info[0]
+ width = info[1]
+ value1 = self._green_param_v - 1.0
+ value2 = self._green_param_s - 1.0
+ for m in range(height):
+ for w in range(width):
+ h, s, v = img_hsl[m, w]
+ b, g, r = img[m, w]
+ tag = abs((int(b) - int(g)) * (int(g) - int(r)))
+ if 43 < s < 255 and 46 < v < 255 and tag > 1600:
+ if 35 < h < 77:
+ b = (b + (b - v) * value2)
+ g = (g + (g - v) * value2)
+ r = (r + (r - v) * value2)
+ b = b + value1 * (255 - b)
+ g = g + value1 * (255 - g)
+ r = r + value1 * (255 - r)
+
+ img[m, w] = [b, g, r]
+
+ return img
+
+
+class HSLCyanItem(MyItem):
+ def __init__(self, parent=None):
+ super(HSLCyanItem, self).__init__('青色', parent=parent)
+ self._cyan_param_s = 1.0
+ self._cyan_param_v = 1.0
+
+ def __call__(self, img):
+ img_hsl = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
+ info = img.shape
+ height = info[0]
+ width = info[1]
+ value1 = self._cyan_param_v - 1.0
+ value2 = self._cyan_param_s - 1.0
+ for m in range(height):
+ for w in range(width):
+ h, s, v = img_hsl[m, w]
+ b, g, r = img[m, w]
+ tag = abs((int(b) - int(g)) * (int(g) - int(r)))
+ if 43 < s < 255 and 46 < v < 255 and tag > 1600:
+ if 78 < h < 99:
+ b = (b + (b - v) * value2)
+ g = (g + (g - v) * value2)
+ r = (r + (r - v) * value2)
+ b = b + value1 * (255 - b)
+ g = g + value1 * (255 - g)
+ r = r + value1 * (255 - r)
+
+ img[m, w] = [b, g, r]
+
+ return img
+
+
+class HSLBlueItem(MyItem):
+ def __init__(self, parent=None):
+ super(HSLBlueItem, self).__init__('蓝色', parent=parent)
+ self._blue_param_s = 1.0
+ self._blue_param_v = 1.0
+
+ def __call__(self, img):
+ img_hsl = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
+ info = img.shape
+ height = info[0]
+ width = info[1]
+ value1 = self._blue_param_v - 1.0
+ value2 = self._blue_param_s - 1.0
+ for m in range(height):
+ for w in range(width):
+ h, s, v = img_hsl[m, w]
+ b, g, r = img[m, w]
+ tag = abs((int(b) - int(g)) * (int(g) - int(r)))
+ if 43 < s < 255 and 46 < v < 255 and tag > 1600:
+ if 100 < h < 124:
+ b = (b + (b - v) * value2)
+ g = (g + (g - v) * value2)
+ r = (r + (r - v) * value2)
+ b = b + value1 * (255 - b)
+ g = g + value1 * (255 - g)
+ r = r + value1 * (255 - r)
+
+ img[m, w] = [b, g, r]
+
+ return img
+
+
+class HSLPurpleItem(MyItem):
+ def __init__(self, parent=None):
+ super(HSLPurpleItem, self).__init__('紫色', parent=parent)
+ self._purple_param_s = 1.0
+ self._purple_param_v = 1.0
+
+ def __call__(self, img):
+ img_hsl = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
+ info = img.shape
+ height = info[0]
+ width = info[1]
+ value1 = self._purple_param_v - 1.0
+ value2 = self._purple_param_s - 1.0
+ for m in range(height):
+ for w in range(width):
+ h, s, v = img_hsl[m, w]
+ b, g, r = img[m, w]
+ tag = abs((int(b) - int(g)) * (int(g) - int(r)))
+ if 43 < s < 255 and 46 < v < 255 and tag > 1600:
+ if 125 < h < 155:
+ b = (b + (b - v) * value2)
+ g = (g + (g - v) * value2)
+ r = (r + (r - v) * value2)
+ b = b + value1 * (255 - b)
+ g = g + value1 * (255 - g)
+ r = r + value1 * (255 - r)
+
+ img[m, w] = [b, g, r]
+
+ return img
+
+
+class PixelateItem(MyItem):
+ def __init__(self, parent=None):
+ super(PixelateItem, self).__init__('像素化', parent=parent)
+ self._size = 100
+
+ def __call__(self, img):
+ height, width = img.shape[:2]
+
+ # Desired "pixelated" size
+
+ w, h = (self._size, self._size)
+
+ # Resize input to "pixelated" size
+
+ temp = cv2.resize(img, (w, h), interpolation=cv2.INTER_LINEAR)
+
+ # Initialize output image
+
+ img = cv2.resize(temp, (width, height), interpolation=cv2.INTER_NEAREST)
+ return img
+
+
+class BlurItem(MyItem):
+ def __init__(self, parent=None):
+ super(BlurItem, self).__init__('模糊', parent=parent)
+ self._size = 5
+
+ def __call__(self, img):
+ img = cv2.blur(img, (self._size, self._size))
+ return img
+
+
+class CandyStyleTransformItem(MyItem):
+ def __init__(self, parent=None):
+ super(CandyStyleTransformItem, self).__init__('candy', parent=parent)
+
+ def __call__(self, img):
+ net = cv2.dnn.readNetFromTorch("./style/candy.t7")
+ net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
+ # img = cv2.imread("D:\\t\\1.jpg")
+ # res = cv2.resize(img, (500, 300))
+ row, column, _ = img.shape
+ blob = cv2.dnn.blobFromImage(img, 1.0, (column, row), (103.939, 116.779, 123.680), swapRB=False, crop=False)
+ net.setInput(blob)
+ out = net.forward()
+ out = out.reshape(3, out.shape[2], out.shape[3])
+ out[0] += 103.939
+ out[1] += 116.779
+ out[2] += 123.680
+ # output = out/255
+ out = out.transpose(1, 2, 0)
+ # output = output.transpose(1, 2, 0)
+ # cv2.imshow("out", output)
+ cv2.imwrite("tmp.jpg", out)
+ out2 = cv2.imread("tmp.jpg")
+ # out_res = cv2.resize(out, (500, 300))
+ return out2
+
+
+class CompositionStyleTransformItem(MyItem):
+ def __init__(self, parent=None):
+ super(CompositionStyleTransformItem, self).__init__('composition', parent=parent)
+
+ def __call__(self, img):
+ net = cv2.dnn.readNetFromTorch("./style/composition_vii.t7")
+ net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
+ # img = cv2.imread("D:\\t\\1.jpg")
+ # res = cv2.resize(img, (500, 300))
+ row, column, _ = img.shape
+ blob = cv2.dnn.blobFromImage(img, 1.0, (column, row), (103.939, 116.779, 123.680), swapRB=False, crop=False)
+ net.setInput(blob)
+ out = net.forward()
+ out = out.reshape(3, out.shape[2], out.shape[3])
+ out[0] += 103.939
+ out[1] += 116.779
+ out[2] += 123.680
+ # output = out/255
+ out = out.transpose(1, 2, 0)
+ # output = output.transpose(1, 2, 0)
+ # cv2.imshow("out", output)
+ cv2.imwrite("tmp.jpg", out)
+ out2 = cv2.imread("tmp.jpg")
+ # out_res = cv2.resize(out, (500, 300))
+ return out2
+
+
+class FeathersStyleTransformItem(MyItem):
+ def __init__(self, parent=None):
+ super(FeathersStyleTransformItem, self).__init__('feathers', parent=parent)
+
+ def __call__(self, img):
+ net = cv2.dnn.readNetFromTorch("./style/feathers.t7")
+ net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
+ # img = cv2.imread("D:\\t\\1.jpg")
+ # res = cv2.resize(img, (500, 300))
+ row, column, _ = img.shape
+ blob = cv2.dnn.blobFromImage(img, 1.0, (column, row), (103.939, 116.779, 123.680), swapRB=False, crop=False)
+ net.setInput(blob)
+ out = net.forward()
+ out = out.reshape(3, out.shape[2], out.shape[3])
+ out[0] += 103.939
+ out[1] += 116.779
+ out[2] += 123.680
+ # output = out/255
+ out = out.transpose(1, 2, 0)
+ # output = output.transpose(1, 2, 0)
+ # cv2.imshow("out", output)
+ cv2.imwrite("tmp.jpg", out)
+ out2 = cv2.imread("tmp.jpg")
+ # out_res = cv2.resize(out, (500, 300))
+ return out2
+
+
+class MuseStyleTransformItem(MyItem):
+ def __init__(self, parent=None):
+ super(MuseStyleTransformItem, self).__init__('la_muse', parent=parent)
+
+ def __call__(self, img):
+ net = cv2.dnn.readNetFromTorch("./style/la_muse.t7")
+ net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
+ # img = cv2.imread("D:\\t\\1.jpg")
+ # res = cv2.resize(img, (500, 300))
+ row, column, _ = img.shape
+ blob = cv2.dnn.blobFromImage(img, 1.0, (column, row), (103.939, 116.779, 123.680), swapRB=False, crop=False)
+ net.setInput(blob)
+ out = net.forward()
+ out = out.reshape(3, out.shape[2], out.shape[3])
+ out[0] += 103.939
+ out[1] += 116.779
+ out[2] += 123.680
+ # output = out/255
+ out = out.transpose(1, 2, 0)
+ # output = output.transpose(1, 2, 0)
+ # cv2.imshow("out", output)
+ cv2.imwrite("tmp.jpg", out)
+ out2 = cv2.imread("tmp.jpg")
+ # out_res = cv2.resize(out, (500, 300))
+ return out2
+
+
+class MosaicStyleTransformItem(MyItem):
+ def __init__(self, parent=None):
+ super(MosaicStyleTransformItem, self).__init__('mosaic', parent=parent)
+
+ def __call__(self, img):
+ net = cv2.dnn.readNetFromTorch("./style/mosaic.t7")
+ net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
+ # img = cv2.imread("D:\\t\\1.jpg")
+ # res = cv2.resize(img, (500, 300))
+ row, column, _ = img.shape
+ blob = cv2.dnn.blobFromImage(img, 1.0, (column, row), (103.939, 116.779, 123.680), swapRB=False, crop=False)
+ net.setInput(blob)
+ out = net.forward()
+ out = out.reshape(3, out.shape[2], out.shape[3])
+ out[0] += 103.939
+ out[1] += 116.779
+ out[2] += 123.680
+ # output = out/255
+ out = out.transpose(1, 2, 0)
+ # output = output.transpose(1, 2, 0)
+ # cv2.imshow("out", output)
+ cv2.imwrite("tmp.jpg", out)
+ out2 = cv2.imread("tmp.jpg")
+ # out_res = cv2.resize(out, (500, 300))
+ return out2
+
+
+class StarryNightStyleTransformItem(MyItem):
+ def __init__(self, parent=None):
+ super(StarryNightStyleTransformItem, self).__init__('starry_night', parent=parent)
+
+ def __call__(self, img):
+ net = cv2.dnn.readNetFromTorch("./style/starry_night.t7")
+ net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
+ # img = cv2.imread("D:\\t\\1.jpg")
+ # res = cv2.resize(img, (500, 300))
+ row, column, _ = img.shape
+ blob = cv2.dnn.blobFromImage(img, 1.0, (column, row), (103.939, 116.779, 123.680), swapRB=False, crop=False)
+ net.setInput(blob)
+ out = net.forward()
+ out = out.reshape(3, out.shape[2], out.shape[3])
+ out[0] += 103.939
+ out[1] += 116.779
+ out[2] += 123.680
+ # output = out/255
+ out = out.transpose(1, 2, 0)
+ # output = output.transpose(1, 2, 0)
+ # cv2.imshow("out", output)
+ cv2.imwrite("tmp.jpg", out)
+ out2 = cv2.imread("tmp.jpg")
+ # out_res = cv2.resize(out, (500, 300))
+ return out2
+
+
+class ScreamStyleTransformItem(MyItem):
+ def __init__(self, parent=None):
+ super(ScreamStyleTransformItem, self).__init__('the_scream', parent=parent)
+
+ def __call__(self, img):
+ net = cv2.dnn.readNetFromTorch("./style/the_scream.t7")
+ net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
+ # img = cv2.imread("D:\\t\\1.jpg")
+ # res = cv2.resize(img, (500, 300))
+ row, column, _ = img.shape
+ blob = cv2.dnn.blobFromImage(img, 1.0, (column, row), (103.939, 116.779, 123.680), swapRB=False, crop=False)
+ net.setInput(blob)
+ out = net.forward()
+ out = out.reshape(3, out.shape[2], out.shape[3])
+ out[0] += 103.939
+ out[1] += 116.779
+ out[2] += 123.680
+ # output = out/255
+ out = out.transpose(1, 2, 0)
+ # output = output.transpose(1, 2, 0)
+ # cv2.imshow("out", output)
+ cv2.imwrite("tmp.jpg", out)
+ out2 = cv2.imread("tmp.jpg")
+ # out_res = cv2.resize(out, (500, 300))
+ return out2
+
+
+class WaveStyleTransformItem(MyItem):
+ def __init__(self, parent=None):
+ super(WaveStyleTransformItem, self).__init__('the_wave', parent=parent)
+
+ def __call__(self, img):
+ net = cv2.dnn.readNetFromTorch("./style/the_wave.t7")
+ net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
+ # img = cv2.imread("D:\\t\\1.jpg")
+ # res = cv2.resize(img, (500, 300))
+ row, column, _ = img.shape
+ blob = cv2.dnn.blobFromImage(img, 1.0, (column, row), (103.939, 116.779, 123.680), swapRB=False, crop=False)
+ net.setInput(blob)
+ out = net.forward()
+ out = out.reshape(3, out.shape[2], out.shape[3])
+ out[0] += 103.939
+ out[1] += 116.779
+ out[2] += 123.680
+ # output = out/255
+ out = out.transpose(1, 2, 0)
+ # output = output.transpose(1, 2, 0)
+ # cv2.imshow("out", output)
+ cv2.imwrite("tmp.jpg", out)
+ out2 = cv2.imread("tmp.jpg")
+ # out_res = cv2.resize(out, (500, 300))
+ return out2
+
+
+class UdnieStyleTransformItem(MyItem):
+ def __init__(self, parent=None):
+ super(UdnieStyleTransformItem, self).__init__('udnie', parent=parent)
+
+ def __call__(self, img):
+ net = cv2.dnn.readNetFromTorch("./style/udnie.t7")
+ net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
+ # img = cv2.imread("D:\\t\\1.jpg")
+ # res = cv2.resize(img, (500, 300))
+ row, column, _ = img.shape
+ blob = cv2.dnn.blobFromImage(img, 1.0, (column, row), (103.939, 116.779, 123.680), swapRB=False, crop=False)
+ net.setInput(blob)
+ out = net.forward()
+ out = out.reshape(3, out.shape[2], out.shape[3])
+ out[0] += 103.939
+ out[1] += 116.779
+ out[2] += 123.680
+ # output = out/255
+ out = out.transpose(1, 2, 0)
+ # output = output.transpose(1, 2, 0)
+ # cv2.imshow("out", output)
+ cv2.imwrite("tmp.jpg", out)
+ out2 = cv2.imread("tmp.jpg")
+ # out_res = cv2.resize(out, (500, 300))
+ return out2
+
+
+class ClarityItem(MyItem):
+ def __init__(self, parent=None):
+ super(ClarityItem, self).__init__('锐化', parent=parent)
+
+ def __call__(self, img):
+ kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32)
+ dst = cv2.filter2D(img, -1, kernel=kernel)
+ return dst
+
+
+class NoiseItem(MyItem):
+ def __init__(self, parent=None):
+ super(NoiseItem, self).__init__('噪点', parent=parent)
+
+ def __call__(self, img):
+ num = int(0.02 * img.shape[0] * img.shape[1]) # 椒盐噪声点数量
+ random.randint(0, img.shape[0])
+ img2 = img.copy()
+ for i in range(num):
+ X = random.randint(0, img2.shape[0] - 1) # 从0到图像长度之间的一个随机整数,因为是闭区间所以-1
+ Y = random.randint(0, img2.shape[1] - 1)
+ if random.randint(0, 1) == 0: # 黑白色概率55开
+ img2[X, Y] = (255, 255, 255) # 白色
+ else:
+ img2[X, Y] = (0, 0, 0) # 黑色
+ return img2
+
+
+class ImageCutItem(MyItem):
+ def __init__(self, parent=None):
+ super(ImageCutItem, self).__init__('裁剪', parent=parent)
+ self._x1 = 0
+ self._x2 = 300
+ self._y1 = 200
+ self._y2 = 600
+
+ def __call__(self, img):
+ dst = img[self._y1:self._y2, self._x1:self._x2]
+ return dst
+
+
+
diff --git a/custom/listWidgets.py b/custom/listWidgets.py
new file mode 100644
index 0000000..4c955a5
--- /dev/null
+++ b/custom/listWidgets.py
@@ -0,0 +1,310 @@
+from PyQt5.QtGui import *
+from PyQt5.QtCore import *
+from PyQt5.QtWidgets import *
+
+from config import items, items1, items2, items3, items4, items5, items6, items7
+
+
+class MyListWidget(QListWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.mainwindow = parent
+ self.setDragEnabled(True)
+ # 选中不显示虚线
+ # self.setEditTriggers(QAbstractItemView.NoEditTriggers)
+ self.setFocusPolicy(Qt.NoFocus)
+
+
+class UsedListWidget(MyListWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.setAcceptDrops(True)
+ self.setFlow(QListView.TopToBottom) # 设置列表方向
+ self.setDefaultDropAction(Qt.MoveAction) # 设置拖放为移动而不是复制一个
+ self.setDragDropMode(QAbstractItemView.InternalMove) # 设置拖放模式, 内部拖放
+ self.itemClicked.connect(self.show_attr)
+ self.setMinimumWidth(200)
+
+ self.move_item = None
+
+ def contextMenuEvent(self, e):
+ # 右键菜单事件
+ item = self.itemAt(self.mapFromGlobal(QCursor.pos()))
+ if not item:
+ return # 判断是否是空白区域
+ menu = QMenu()
+ delete_action = QAction('删除', self)
+ delete_action.triggered.connect(lambda: self.delete_item(item)) # 传递额外值
+ menu.addAction(delete_action)
+ menu.exec(QCursor.pos())
+
+ def delete_item(self, item):
+ # 删除操作
+ self.takeItem(self.row(item))
+ self.mainwindow.update_image() # 更新frame
+ self.mainwindow.dock_attr.close()
+
+ def dropEvent(self, event):
+ super().dropEvent(event)
+ self.mainwindow.update_image()
+
+ def show_attr(self):
+ item = self.itemAt(self.mapFromGlobal(QCursor.pos()))
+ if not item:
+ return
+ param = item.get_params() # 获取当前item的属性
+ if type(item) in items:
+ index = items.index(type(item)) # 获取item对应的table索引
+ self.mainwindow.stackedWidget.setCurrentIndex(index)
+ self.mainwindow.stackedWidget.currentWidget().update_params(param) # 更新对应的table
+ self.mainwindow.dock_attr.show()
+ if type(item) in items1:
+ index = items1.index(type(item)) # 获取item对应的table索引
+ self.mainwindow.stackedWidget.setCurrentIndex(index + 10)
+ self.mainwindow.stackedWidget.currentWidget().update_params(param) # 更新对应的table
+ self.mainwindow.dock_attr.show()
+ if type(item) in items2:
+ index = items2.index(type(item)) # 获取item对应的table索引
+ self.mainwindow.stackedWidget.setCurrentIndex(index + 15)
+ self.mainwindow.stackedWidget.currentWidget().update_params(param) # 更新对应的table
+ self.mainwindow.dock_attr.show()
+ if type(item) in items3:
+ index = items3.index(type(item)) # 获取item对应的table索引
+ self.mainwindow.stackedWidget.setCurrentIndex(index + 18)
+ self.mainwindow.stackedWidget.currentWidget().update_params(param) # 更新对应的table
+ self.mainwindow.dock_attr.show()
+ if type(item) in items4:
+ index = items4.index(type(item)) # 获取item对应的table索引
+ self.mainwindow.stackedWidget.setCurrentIndex(index + 21)
+ self.mainwindow.stackedWidget.currentWidget().update_params(param) # 更新对应的table
+ self.mainwindow.dock_attr.show()
+ if type(item) in items5:
+ index = items5.index(type(item)) # 获取item对应的table索引
+ self.mainwindow.stackedWidget.setCurrentIndex(index + 28)
+ self.mainwindow.stackedWidget.currentWidget().update_params(param) # 更新对应的table
+ self.mainwindow.dock_attr.show()
+ if type(item) in items6: # 获取item对应的table索引
+ self.mainwindow.stackedWidget.setCurrentIndex(30)
+ self.mainwindow.stackedWidget.currentWidget().update_params(param) # 更新对应的table
+ self.mainwindow.dock_attr.show()
+ if type(item) in items7: # 获取item对应的table索引
+ self.mainwindow.stackedWidget.setCurrentIndex(30)
+ self.mainwindow.stackedWidget.currentWidget().update_params(param) # 更新对应的table
+ self.mainwindow.dock_attr.show()
+
+
+class FuncListWidget(MyListWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.setFixedHeight(64 * 3)
+ self.setFlow(QListView.LeftToRight) # 设置列表方向
+ self.setViewMode(QListView.IconMode) # 设置列表模式
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 关掉滑动条
+ self.setAcceptDrops(False)
+ for itemType in items:
+ self.addItem(itemType())
+ self.itemClicked.connect(self.add_used_function)
+
+ def add_used_function(self):
+ func_item = self.currentItem()
+ if type(func_item) in items:
+ use_item = type(func_item)()
+ self.mainwindow.useListWidget.addItem(use_item)
+ self.mainwindow.update_image()
+
+ def enterEvent(self, event):
+ self.setCursor(Qt.PointingHandCursor)
+
+ def leaveEvent(self, event):
+ self.setCursor(Qt.ArrowCursor)
+ self.setCurrentRow(-1) # 取消选中状态
+
+
+class FuncListWidget1(MyListWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.setFixedHeight(64 * 3)
+ self.setFlow(QListView.LeftToRight) # 设置列表方向
+ self.setViewMode(QListView.IconMode) # 设置列表模式
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 关掉滑动条
+ self.setAcceptDrops(False)
+ for itemType in items1:
+ self.addItem(itemType())
+ self.itemClicked.connect(self.add_used_function)
+
+ def add_used_function(self):
+ func_item = self.currentItem()
+ if type(func_item) in items1:
+ use_item = type(func_item)()
+ self.mainwindow.useListWidget.addItem(use_item)
+ self.mainwindow.update_image()
+
+ def enterEvent(self, event):
+ self.setCursor(Qt.PointingHandCursor)
+
+ def leaveEvent(self, event):
+ self.setCursor(Qt.ArrowCursor)
+ self.setCurrentRow(-1) # 取消选中状态
+
+
+class FuncListWidget2(MyListWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.setFixedHeight(64 * 3)
+ self.setFlow(QListView.LeftToRight) # 设置列表方向
+ self.setViewMode(QListView.IconMode) # 设置列表模式
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 关掉滑动条
+ self.setAcceptDrops(False)
+ for itemType in items2:
+ self.addItem(itemType())
+ self.itemClicked.connect(self.add_used_function)
+
+ def add_used_function(self):
+ func_item = self.currentItem()
+ if type(func_item) in items2:
+ use_item = type(func_item)()
+ self.mainwindow.useListWidget.addItem(use_item)
+ self.mainwindow.update_image()
+
+ def enterEvent(self, event):
+ self.setCursor(Qt.PointingHandCursor)
+
+ def leaveEvent(self, event):
+ self.setCursor(Qt.ArrowCursor)
+ self.setCurrentRow(-1) # 取消选中状态
+
+
+class FuncListWidget3(MyListWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.setFixedHeight(64 * 3)
+ self.setFlow(QListView.LeftToRight) # 设置列表方向
+ self.setViewMode(QListView.IconMode) # 设置列表模式
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 关掉滑动条
+ self.setAcceptDrops(False)
+ for itemType in items3:
+ self.addItem(itemType())
+ self.itemClicked.connect(self.add_used_function)
+
+ def add_used_function(self):
+ func_item = self.currentItem()
+ if type(func_item) in items3:
+ use_item = type(func_item)()
+ self.mainwindow.useListWidget.addItem(use_item)
+ self.mainwindow.update_image()
+
+ def enterEvent(self, event):
+ self.setCursor(Qt.PointingHandCursor)
+
+ def leaveEvent(self, event):
+ self.setCursor(Qt.ArrowCursor)
+ self.setCurrentRow(-1) # 取消选中状态
+
+
+class FuncListWidget4(MyListWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.setFixedHeight(64 * 3)
+ self.setFlow(QListView.LeftToRight) # 设置列表方向
+ self.setViewMode(QListView.IconMode) # 设置列表模式
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 关掉滑动条
+ self.setAcceptDrops(False)
+ for itemType in items4:
+ self.addItem(itemType())
+ self.itemClicked.connect(self.add_used_function)
+
+ def add_used_function(self):
+ func_item = self.currentItem()
+ if type(func_item) in items4:
+ use_item = type(func_item)()
+ self.mainwindow.useListWidget.addItem(use_item)
+ self.mainwindow.update_image()
+
+ def enterEvent(self, event):
+ self.setCursor(Qt.PointingHandCursor)
+
+ def leaveEvent(self, event):
+ self.setCursor(Qt.ArrowCursor)
+ self.setCurrentRow(-1) # 取消选中状态
+
+
+class FuncListWidget5(MyListWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.setFixedHeight(64 * 3)
+ self.setFlow(QListView.LeftToRight) # 设置列表方向
+ self.setViewMode(QListView.IconMode) # 设置列表模式
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 关掉滑动条
+ self.setAcceptDrops(False)
+ for itemType in items5:
+ self.addItem(itemType())
+ self.itemClicked.connect(self.add_used_function)
+
+ def add_used_function(self):
+ func_item = self.currentItem()
+ if type(func_item) in items5:
+ use_item = type(func_item)()
+ self.mainwindow.useListWidget.addItem(use_item)
+ self.mainwindow.update_image()
+
+ def enterEvent(self, event):
+ self.setCursor(Qt.PointingHandCursor)
+
+ def leaveEvent(self, event):
+ self.setCursor(Qt.ArrowCursor)
+ self.setCurrentRow(-1) # 取消选中状态
+
+
+class FuncListWidget6(MyListWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.setFixedHeight(64 * 3)
+ self.setFlow(QListView.LeftToRight) # 设置列表方向
+ self.setViewMode(QListView.IconMode) # 设置列表模式
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 关掉滑动条
+ self.setAcceptDrops(False)
+ for itemType in items6:
+ self.addItem(itemType())
+ self.itemClicked.connect(self.add_used_function)
+
+ def add_used_function(self):
+ func_item = self.currentItem()
+ if type(func_item) in items6:
+ use_item = type(func_item)()
+ self.mainwindow.useListWidget.addItem(use_item)
+ self.mainwindow.update_image()
+
+ def enterEvent(self, event):
+ self.setCursor(Qt.PointingHandCursor)
+
+ def leaveEvent(self, event):
+ self.setCursor(Qt.ArrowCursor)
+ self.setCurrentRow(-1) # 取消选中状态
+
+
+class FuncListWidget7(MyListWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.setFixedHeight(64 * 3)
+ self.setFlow(QListView.LeftToRight) # 设置列表方向
+ self.setViewMode(QListView.IconMode) # 设置列表模式
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 关掉滑动条
+ self.setAcceptDrops(False)
+ for itemType in items7:
+ self.addItem(itemType())
+ self.itemClicked.connect(self.add_used_function)
+
+ def add_used_function(self):
+ func_item = self.currentItem()
+ if type(func_item) in items7:
+ use_item = type(func_item)()
+ self.mainwindow.useListWidget.addItem(use_item)
+ self.mainwindow.update_image()
+
+ def enterEvent(self, event):
+ self.setCursor(Qt.PointingHandCursor)
+
+ def leaveEvent(self, event):
+ self.setCursor(Qt.ArrowCursor)
+ self.setCurrentRow(-1) # 取消选中状态
+
diff --git a/custom/stackedWidget.py b/custom/stackedWidget.py
new file mode 100644
index 0000000..e7290a9
--- /dev/null
+++ b/custom/stackedWidget.py
@@ -0,0 +1,10 @@
+from custom.tableWidget import *
+from config import tables
+
+
+class StackedWidget(QStackedWidget):
+ def __init__(self, parent):
+ super().__init__(parent=parent)
+ for table in tables:
+ self.addWidget(table(parent=parent))
+ self.setMinimumWidth(200)
diff --git a/custom/styleSheet.qss b/custom/styleSheet.qss
new file mode 100644
index 0000000..a244671
--- /dev/null
+++ b/custom/styleSheet.qss
@@ -0,0 +1,86 @@
+*{
+ font-family: 微软雅黑;
+ color: #BBBBBB;
+ background-color: #2F2F2F;
+}
+
+/* 设置目录树样式 */
+QTreeView{
+ show-decoration-selected: 1;
+}
+QTreeView::item{
+ height: 30px;
+}
+QTreeView::item:hover, QTreeView::branch:hover{
+ background: #4B6EAF;
+}
+QTreeView::item:selected, QTreeView::branch:selected{
+ background: #4B6EAF;
+}
+QTreeView::branch{
+ color: #BBBBBB;
+}
+QTreeView::branch:has-children:!has-siblings:closed,
+QTreeView::branch:closed:has-children:has-siblings {
+ border-image: none;
+ image: url(icons/branch-close.png);
+}
+QTreeView::branch:open:has-children:!has-siblings,
+QTreeView::branch:open:has-children:has-siblings {
+ border-image: none;
+ image: url(icons/branch-open.png);
+}
+
+/* 设置标签样式 */
+QLabel{
+ font-size: 18px;
+ border: 1px solid #BBBBBB;
+ border-width: 1px 1px 0px 1px;
+}
+
+/* 设置视图样式 */
+QGraphicsView{
+ border: 1px solid #BBBBBB;
+ background-color: #444444;
+}
+
+/* 设置列表样式 */
+QListWidget::Item{
+ border: 1px solid #BBBBBB;
+ font-size: 20px;
+ background: #717678;
+ color: #DDDDDD;
+}
+
+QListWidget::Item:hover{
+ background: #4B6EAF;
+}
+
+FuncListWidget::Item{
+ border-style: inset;
+ border-radius: 8px;
+ border: 1px solid #999999;
+ margin:0px 1px 0px 0px
+}
+
+UsedListWidget::Item{
+ border: 2px solid #999999;
+ margin:0px 0px 1px 0px
+}
+
+UsedListWidget::Item:selected{
+ background: #99CCFF;
+}
+
+
+/* 设置表格样式 */
+QTableWidget{
+ alternate-background-color: #444444;
+}
+
+
+QToolButton:hover{
+ background: #4B6EAF;
+}
+
+
diff --git a/custom/tableWidget.py b/custom/tableWidget.py
new file mode 100644
index 0000000..f8238bd
--- /dev/null
+++ b/custom/tableWidget.py
@@ -0,0 +1,690 @@
+from PyQt5.QtWidgets import *
+from PyQt5.QtCore import *
+
+
+class TableWidget(QTableWidget):
+ def __init__(self, parent=None):
+ super(TableWidget, self).__init__(parent=parent)
+ self.mainwindow = parent
+ self.setShowGrid(True) # 显示网格
+ self.setAlternatingRowColors(True) # 隔行显示颜色
+ self.setEditTriggers(QAbstractItemView.NoEditTriggers)
+ self.horizontalHeader().setVisible(False)
+ self.verticalHeader().setVisible(False)
+ self.horizontalHeader().sectionResizeMode(QHeaderView.Stretch)
+ self.verticalHeader().sectionResizeMode(QHeaderView.Stretch)
+ self.horizontalHeader().setStretchLastSection(True)
+ self.setFocusPolicy(Qt.NoFocus)
+
+ def signal_connect(self):
+ for spinbox in self.findChildren(QSpinBox):
+ spinbox.valueChanged.connect(self.update_item)
+ for doublespinbox in self.findChildren(QDoubleSpinBox):
+ doublespinbox.valueChanged.connect(self.update_item)
+ for combox in self.findChildren(QComboBox):
+ combox.currentIndexChanged.connect(self.update_item)
+ for checkbox in self.findChildren(QCheckBox):
+ checkbox.stateChanged.connect(self.update_item)
+
+ def update_item(self):
+ param = self.get_params()
+ self.mainwindow.useListWidget.currentItem().update_params(param)
+ self.mainwindow.update_image()
+
+ def update_params(self, param=None):
+ for key in param.keys():
+ box = self.findChild(QWidget, name=key)
+ if isinstance(box, QSpinBox) or isinstance(box, QDoubleSpinBox):
+ box.setValue(param[key])
+ elif isinstance(box, QComboBox):
+ box.setCurrentIndex(param[key])
+ elif isinstance(box, QCheckBox):
+ box.setChecked(param[key])
+
+ def get_params(self):
+ param = {}
+ for spinbox in self.findChildren(QSpinBox):
+ param[spinbox.objectName()] = spinbox.value()
+ for doublespinbox in self.findChildren(QDoubleSpinBox):
+ param[doublespinbox.objectName()] = doublespinbox.value()
+ for combox in self.findChildren(QComboBox):
+ param[combox.objectName()] = combox.currentIndex()
+ for combox in self.findChildren(QCheckBox):
+ param[combox.objectName()] = combox.isChecked()
+ return param
+
+
+class GrayingTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(GrayingTableWidget, self).__init__(parent=parent)
+
+
+class FilterTabledWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(FilterTabledWidget, self).__init__(parent=parent)
+
+ self.kind_comBox = QComboBox()
+ self.kind_comBox.addItems(['均值滤波', '高斯滤波', '中值滤波'])
+ self.kind_comBox.setObjectName('kind')
+
+ self.ksize_spinBox = QSpinBox()
+ self.ksize_spinBox.setObjectName('ksize')
+ self.ksize_spinBox.setMinimum(1)
+ self.ksize_spinBox.setSingleStep(2)
+
+ self.setColumnCount(2)
+ self.setRowCount(2)
+ self.setItem(0, 0, QTableWidgetItem('类型'))
+ self.setCellWidget(0, 1, self.kind_comBox)
+ self.setItem(1, 0, QTableWidgetItem('核大小'))
+ self.setCellWidget(1, 1, self.ksize_spinBox)
+
+ self.signal_connect()
+
+
+class MorphTabledWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(MorphTabledWidget, self).__init__(parent=parent)
+
+ self.op_comBox = QComboBox()
+ self.op_comBox.addItems(['腐蚀操作', '膨胀操作', '开操作', '闭操作', '梯度操作', '顶帽操作', '黑帽操作'])
+ self.op_comBox.setObjectName('op')
+
+ self.ksize_spinBox = QSpinBox()
+ self.ksize_spinBox.setMinimum(1)
+ self.ksize_spinBox.setSingleStep(2)
+ self.ksize_spinBox.setObjectName('ksize')
+
+ self.kshape_comBox = QComboBox()
+ self.kshape_comBox.addItems(['方形', '十字形', '椭圆形'])
+ self.kshape_comBox.setObjectName('kshape')
+
+ self.setColumnCount(2)
+ self.setRowCount(3)
+ self.setItem(0, 0, QTableWidgetItem('类型'))
+ self.setCellWidget(0, 1, self.op_comBox)
+ self.setItem(1, 0, QTableWidgetItem('核大小'))
+ self.setCellWidget(1, 1, self.ksize_spinBox)
+ self.setItem(2, 0, QTableWidgetItem('核形状'))
+ self.setCellWidget(2, 1, self.kshape_comBox)
+ self.signal_connect()
+
+
+class GradTabledWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(GradTabledWidget, self).__init__(parent=parent)
+
+ self.kind_comBox = QComboBox()
+ self.kind_comBox.addItems(['Sobel算子', 'Scharr算子', 'Laplacian算子'])
+ self.kind_comBox.setObjectName('kind')
+
+ self.ksize_spinBox = QSpinBox()
+ self.ksize_spinBox.setMinimum(1)
+ self.ksize_spinBox.setSingleStep(2)
+ self.ksize_spinBox.setObjectName('ksize')
+
+ self.dx_spinBox = QSpinBox()
+ self.dx_spinBox.setMaximum(1)
+ self.dx_spinBox.setMinimum(0)
+ self.dx_spinBox.setSingleStep(1)
+ self.dx_spinBox.setObjectName('dx')
+
+ self.dy_spinBox = QSpinBox()
+ self.dy_spinBox.setMaximum(1)
+ self.dy_spinBox.setMinimum(0)
+ self.dy_spinBox.setSingleStep(1)
+ self.dy_spinBox.setObjectName('dy')
+
+ self.setColumnCount(2)
+ self.setRowCount(4)
+
+ self.setItem(0, 0, QTableWidgetItem('类型'))
+ self.setCellWidget(0, 1, self.kind_comBox)
+ self.setItem(1, 0, QTableWidgetItem('核大小'))
+ self.setCellWidget(1, 1, self.ksize_spinBox)
+ self.setItem(2, 0, QTableWidgetItem('x方向'))
+ self.setCellWidget(2, 1, self.dx_spinBox)
+ self.setItem(3, 0, QTableWidgetItem('y方向'))
+ self.setCellWidget(3, 1, self.dy_spinBox)
+
+ self.signal_connect()
+
+
+class ThresholdTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(ThresholdTableWidget, self).__init__(parent=parent)
+
+ self.thresh_spinBox = QSpinBox()
+ self.thresh_spinBox.setObjectName('thresh')
+ self.thresh_spinBox.setMaximum(255)
+ self.thresh_spinBox.setMinimum(0)
+ self.thresh_spinBox.setSingleStep(1)
+
+ self.maxval_spinBox = QSpinBox()
+ self.maxval_spinBox.setObjectName('maxval')
+ self.maxval_spinBox.setMaximum(255)
+ self.maxval_spinBox.setMinimum(0)
+ self.maxval_spinBox.setSingleStep(1)
+
+ self.method_comBox = QComboBox()
+ self.method_comBox.addItems(['二进制阈值化', '反二进制阈值化', '截断阈值化', '阈值化为0', '反阈值化为0', '大津算法'])
+ self.method_comBox.setObjectName('method')
+
+ self.setColumnCount(2)
+ self.setRowCount(3)
+
+ self.setItem(0, 0, QTableWidgetItem('类型'))
+ self.setCellWidget(0, 1, self.method_comBox)
+ self.setItem(1, 0, QTableWidgetItem('阈值'))
+ self.setCellWidget(1, 1, self.thresh_spinBox)
+ self.setItem(2, 0, QTableWidgetItem('最大值'))
+ self.setCellWidget(2, 1, self.maxval_spinBox)
+
+ self.signal_connect()
+
+
+class EdgeTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(EdgeTableWidget, self).__init__(parent=parent)
+
+ self.thresh1_spinBox = QSpinBox()
+ self.thresh1_spinBox.setMinimum(0)
+ self.thresh1_spinBox.setMaximum(255)
+ self.thresh1_spinBox.setSingleStep(1)
+ self.thresh1_spinBox.setObjectName('thresh1')
+
+ self.thresh2_spinBox = QSpinBox()
+ self.thresh2_spinBox.setMinimum(0)
+ self.thresh2_spinBox.setMaximum(255)
+ self.thresh2_spinBox.setSingleStep(1)
+ self.thresh2_spinBox.setObjectName('thresh2')
+
+ self.setColumnCount(2)
+ self.setRowCount(2)
+
+ self.setItem(0, 0, QTableWidgetItem('阈值1'))
+ self.setCellWidget(0, 1, self.thresh1_spinBox)
+ self.setItem(1, 0, QTableWidgetItem('阈值2'))
+ self.setCellWidget(1, 1, self.thresh2_spinBox)
+ self.signal_connect()
+
+
+class ImageCutTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(ImageCutTableWidget, self).__init__(parent=parent)
+
+ self.x1_spinBox = QSpinBox()
+ self.x1_spinBox.setMinimum(1)
+ self.x1_spinBox.setMaximum(5000)
+ self.x1_spinBox.setSingleStep(1)
+ self.x1_spinBox.setObjectName('x1')
+
+ self.y1_spinBox = QSpinBox()
+ self.y1_spinBox.setMinimum(1)
+ self.y1_spinBox.setMaximum(5000)
+ self.y1_spinBox.setSingleStep(1)
+ self.y1_spinBox.setObjectName('y1')
+
+ self.x2_spinBox = QSpinBox()
+ self.x2_spinBox.setMinimum(1)
+ self.x2_spinBox.setMaximum(5000)
+ self.x2_spinBox.setSingleStep(1)
+ self.x2_spinBox.setObjectName('x2')
+
+ self.y2_spinBox = QSpinBox()
+ self.y2_spinBox.setMinimum(1)
+ self.y2_spinBox.setMaximum(5000)
+ self.y2_spinBox.setSingleStep(1)
+ self.y2_spinBox.setObjectName('y2')
+
+ self.setColumnCount(4)
+ self.setRowCount(2)
+
+ self.setItem(0, 0, QTableWidgetItem('x1'))
+ self.setCellWidget(0, 1, self.x1_spinBox)
+ self.setItem(1, 0, QTableWidgetItem('y1'))
+ self.setCellWidget(1, 1, self.y1_spinBox)
+ self.setItem(2, 0, QTableWidgetItem('x2'))
+ self.setCellWidget(2, 1, self.x2_spinBox)
+ self.setItem(3, 0, QTableWidgetItem('y2'))
+ self.setCellWidget(3, 1, self.y2_spinBox)
+ self.signal_connect()
+
+
+class ContourTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(ContourTableWidget, self).__init__(parent=parent)
+
+ self.bbox_comBox = QComboBox()
+ self.bbox_comBox.addItems(['正常轮廓', '外接矩形', '最小外接矩形', '最小外接圆'])
+ self.bbox_comBox.setObjectName('bbox')
+
+ self.mode_comBox = QComboBox()
+ self.mode_comBox.addItems(['外轮廓', '轮廓列表', '外轮廓与内孔', '轮廓等级树'])
+ self.mode_comBox.setObjectName('mode')
+
+ self.method_comBox = QComboBox()
+ self.method_comBox.addItems(['无近似', '简易近似'])
+ self.method_comBox.setObjectName('method')
+
+ self.setColumnCount(2)
+ self.setRowCount(3)
+
+ self.setItem(0, 0, QTableWidgetItem('轮廓模式'))
+ self.setCellWidget(0, 1, self.mode_comBox)
+ self.setItem(1, 0, QTableWidgetItem('轮廓近似'))
+ self.setCellWidget(1, 1, self.method_comBox)
+ self.setItem(2, 0, QTableWidgetItem('边界模式'))
+ self.setCellWidget(2, 1, self.bbox_comBox)
+ self.signal_connect()
+
+
+class EqualizeTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(EqualizeTableWidget, self).__init__(parent=parent)
+ self.red_checkBox = QCheckBox()
+ self.red_checkBox.setObjectName('red')
+ self.red_checkBox.setTristate(False)
+ self.blue_checkBox = QCheckBox()
+ self.blue_checkBox.setObjectName('blue')
+ self.blue_checkBox.setTristate(False)
+ self.green_checkBox = QCheckBox()
+ self.green_checkBox.setObjectName('green')
+ self.green_checkBox.setTristate(False)
+
+ self.setColumnCount(2)
+ self.setRowCount(3)
+
+ self.setItem(0, 0, QTableWidgetItem('R通道'))
+ self.setCellWidget(0, 1, self.red_checkBox)
+ self.setItem(1, 0, QTableWidgetItem('G通道'))
+ self.setCellWidget(1, 1, self.green_checkBox)
+ self.setItem(2, 0, QTableWidgetItem('B通道'))
+ self.setCellWidget(2, 1, self.blue_checkBox)
+ self.signal_connect()
+
+
+class HoughLineTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(HoughLineTableWidget, self).__init__(parent=parent)
+
+ self.thresh_spinBox = QSpinBox()
+ self.thresh_spinBox.setMinimum(0)
+ self.thresh_spinBox.setSingleStep(1)
+ self.thresh_spinBox.setObjectName('thresh')
+
+ self.min_length_spinBox = QSpinBox()
+ self.min_length_spinBox.setMinimum(0)
+ self.min_length_spinBox.setSingleStep(1)
+ self.min_length_spinBox.setObjectName('min_length')
+
+ self.max_gap_spinbox = QSpinBox()
+ self.max_gap_spinbox.setMinimum(0)
+ self.max_gap_spinbox.setSingleStep(1)
+ self.max_gap_spinbox.setObjectName('max_gap')
+
+ self.setColumnCount(2)
+ self.setRowCount(3)
+
+ self.setItem(0, 0, QTableWidgetItem('交点阈值'))
+ self.setCellWidget(0, 1, self.thresh_spinBox)
+ self.setItem(1, 0, QTableWidgetItem('最小长度'))
+ self.setCellWidget(1, 1, self.min_length_spinBox)
+ self.setItem(2, 0, QTableWidgetItem('最大间距'))
+ self.setCellWidget(2, 1, self.max_gap_spinbox)
+ self.signal_connect()
+
+
+class LightTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(LightTableWidget, self).__init__(parent=parent)
+
+ self.alpha_spinBox = QDoubleSpinBox()
+ self.alpha_spinBox.setMinimum(0)
+ self.alpha_spinBox.setMaximum(3)
+ self.alpha_spinBox.setSingleStep(0.1)
+ self.alpha_spinBox.setObjectName('alpha')
+
+ self.beta_spinbox = QSpinBox()
+ self.beta_spinbox.setMinimum(0)
+ self.beta_spinbox.setSingleStep(1)
+ self.beta_spinbox.setObjectName('beta')
+
+ self.setColumnCount(2)
+ self.setRowCount(2)
+
+ self.setItem(0, 0, QTableWidgetItem('alpha'))
+ self.setCellWidget(0, 1, self.alpha_spinBox)
+ self.setItem(1, 0, QTableWidgetItem('beta'))
+ self.setCellWidget(1, 1, self.beta_spinbox)
+ self.signal_connect()
+
+
+class GammaITabelWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(GammaITabelWidget, self).__init__(parent=parent)
+ self.gamma_spinbox = QDoubleSpinBox()
+ self.gamma_spinbox.setMinimum(0)
+ self.gamma_spinbox.setSingleStep(0.1)
+ self.gamma_spinbox.setObjectName('gamma')
+
+ self.setColumnCount(2)
+ self.setRowCount(1)
+
+ self.setItem(0, 0, QTableWidgetItem('gamma'))
+ self.setCellWidget(0, 1, self.gamma_spinbox)
+ self.signal_connect()
+
+
+class RotateAnyTabelWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(RotateAnyTabelWidget, self).__init__(parent=parent)
+ self.angle_spinBox = QSpinBox()
+ self.angle_spinBox.setMinimum(0)
+ self.angle_spinBox.setSingleStep(1)
+ self.angle_spinBox.setMaximum(360)
+ self.angle_spinBox.setObjectName('angle')
+
+ self.setColumnCount(2)
+ self.setRowCount(1)
+ self.setItem(0, 0, QTableWidgetItem('旋转角度'))
+ self.setCellWidget(0, 1, self.angle_spinBox)
+ self.signal_connect()
+
+
+class ExposureTabelWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(ExposureTabelWidget, self).__init__(parent=parent)
+
+ self.alpha_spinBox = QDoubleSpinBox()
+ self.alpha_spinBox.setMinimum(0)
+ self.alpha_spinBox.setMaximum(3)
+ self.alpha_spinBox.setSingleStep(0.1)
+ self.alpha_spinBox.setObjectName('alpha')
+
+ self.setColumnCount(2)
+ self.setRowCount(1)
+
+ self.setItem(0, 0, QTableWidgetItem('曝光度'))
+ self.setCellWidget(0, 1, self.alpha_spinBox)
+ self.signal_connect()
+
+
+class ContrastTabelWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(ContrastTabelWidget, self).__init__(parent=parent)
+
+ self.alpha_spinBox = QDoubleSpinBox()
+ self.alpha_spinBox.setMinimum(0)
+ self.alpha_spinBox.setSingleStep(0.1)
+ self.alpha_spinBox.setObjectName('alpha')
+
+ self.setColumnCount(2)
+ self.setRowCount(1)
+
+ self.setItem(0, 0, QTableWidgetItem('对比度'))
+ self.setCellWidget(0, 1, self.alpha_spinBox)
+ self.signal_connect()
+
+
+class ColorTemperatureTabelWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(ColorTemperatureTabelWidget, self).__init__(parent=parent)
+ self.alpha_spinBox = QSpinBox()
+ self.alpha_spinBox.setRange(-200, 200)
+ self.alpha_spinBox.setSingleStep(1)
+ self.alpha_spinBox.setObjectName('n')
+
+ self.setColumnCount(2)
+ self.setRowCount(1)
+ self.setItem(0, 0, QTableWidgetItem('色温'))
+ self.setCellWidget(0, 1, self.alpha_spinBox)
+ self.signal_connect()
+
+
+class HueTabelWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(HueTabelWidget, self).__init__(parent=parent)
+ self.alpha_spinBox = QSpinBox()
+ self.alpha_spinBox.setRange(-200, 200)
+ self.alpha_spinBox.setSingleStep(1)
+ self.alpha_spinBox.setObjectName('n')
+
+ self.setColumnCount(2)
+ self.setRowCount(1)
+ self.setItem(0, 0, QTableWidgetItem('色调'))
+ self.setCellWidget(0, 1, self.alpha_spinBox)
+ self.signal_connect()
+
+
+class SaturationTabelWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(SaturationTabelWidget, self).__init__(parent=parent)
+ self.angle_spinBox = QSpinBox()
+ self.angle_spinBox.setRange(-50, 50)
+ self.angle_spinBox.setSingleStep(1)
+ self.angle_spinBox.setObjectName('x')
+
+ self.setColumnCount(2)
+ self.setRowCount(1)
+ self.setItem(0, 0, QTableWidgetItem('饱和度'))
+ self.setCellWidget(0, 1, self.angle_spinBox)
+ self.signal_connect()
+
+
+class PixelateTabelWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(PixelateTabelWidget, self).__init__(parent=parent)
+ self.size_spinBox = QSpinBox()
+ self.size_spinBox.setRange(1, 1000)
+ self.size_spinBox.setSingleStep(10)
+ self.size_spinBox.setObjectName('size')
+
+ self.setColumnCount(2)
+ self.setRowCount(1)
+ self.setItem(0, 0, QTableWidgetItem('像素大小'))
+ self.setCellWidget(0, 1, self.size_spinBox)
+ self.signal_connect()
+
+
+class BlurTabelWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(BlurTabelWidget, self).__init__(parent=parent)
+ self.size_spinBox = QSpinBox()
+ self.size_spinBox.setRange(1, 100)
+ self.size_spinBox.setSingleStep(1)
+ self.size_spinBox.setObjectName('size')
+
+ self.setColumnCount(2)
+ self.setRowCount(1)
+ self.setItem(0, 0, QTableWidgetItem('模糊大小'))
+ self.setCellWidget(0, 1, self.size_spinBox)
+ self.signal_connect()
+
+
+class HSLRedWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(HSLRedWidget, self).__init__(parent=parent)
+ self.red_param_s_spinBox = QDoubleSpinBox()
+ self.red_param_s_spinBox.setMinimum(0)
+ self.red_param_s_spinBox.setSingleStep(0.01)
+ self.red_param_s_spinBox.setMaximum(2)
+ self.red_param_s_spinBox.setObjectName('red_param_s')
+
+ self.red_param_v_spinBox = QDoubleSpinBox()
+ self.red_param_v_spinBox.setMinimum(0)
+ self.red_param_v_spinBox.setSingleStep(0.01)
+ self.red_param_v_spinBox.setMaximum(2)
+ self.red_param_v_spinBox.setObjectName('red_param_v')
+
+ self.setColumnCount(2)
+ self.setRowCount(2)
+ self.setItem(0, 0, QTableWidgetItem('红色饱和度'))
+ self.setCellWidget(0, 1, self.red_param_v_spinBox)
+ self.setItem(1, 0, QTableWidgetItem('红色亮度'))
+ self.setCellWidget(1, 1, self.red_param_s_spinBox)
+ self.signal_connect()
+
+
+class HSLOrangeWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(HSLOrangeWidget, self).__init__(parent=parent)
+ self.orange_param_s_spinBox = QDoubleSpinBox()
+ self.orange_param_s_spinBox.setMinimum(0)
+ self.orange_param_s_spinBox.setSingleStep(0.01)
+ self.orange_param_s_spinBox.setMaximum(2)
+ self.orange_param_s_spinBox.setObjectName('orange_param_s')
+
+ self.orange_param_v_spinBox = QDoubleSpinBox()
+ self.orange_param_v_spinBox.setMinimum(0)
+ self.orange_param_v_spinBox.setSingleStep(0.01)
+ self.orange_param_v_spinBox.setMaximum(2)
+ self.orange_param_v_spinBox.setObjectName('orange_param_v')
+
+ self.setColumnCount(2)
+ self.setRowCount(2)
+ self.setItem(0, 0, QTableWidgetItem('橙色饱和度'))
+ self.setCellWidget(0, 1, self.orange_param_v_spinBox)
+ self.setItem(1, 0, QTableWidgetItem('橙色亮度'))
+ self.setCellWidget(1, 1, self.orange_param_s_spinBox)
+ self.signal_connect()
+
+
+class HSLYellowWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(HSLYellowWidget, self).__init__(parent=parent)
+ self.yellow_param_s_spinBox = QDoubleSpinBox()
+ self.yellow_param_s_spinBox.setMinimum(0)
+ self.yellow_param_s_spinBox.setSingleStep(0.01)
+ self.yellow_param_s_spinBox.setMaximum(2)
+ self.yellow_param_s_spinBox.setObjectName('yellow_param_s')
+
+ self.yellow_param_v_spinBox = QDoubleSpinBox()
+ self.yellow_param_v_spinBox.setMinimum(0)
+ self.yellow_param_v_spinBox.setSingleStep(0.01)
+ self.yellow_param_v_spinBox.setMaximum(2)
+ self.yellow_param_v_spinBox.setObjectName('yellow_param_v')
+
+ self.setColumnCount(2)
+ self.setRowCount(2)
+ self.setItem(0, 0, QTableWidgetItem('黄色饱和度'))
+ self.setCellWidget(0, 1, self.yellow_param_v_spinBox)
+ self.setItem(1, 0, QTableWidgetItem('黄色亮度'))
+ self.setCellWidget(1, 1, self.yellow_param_s_spinBox)
+ self.signal_connect()
+
+
+class HSLGreenWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(HSLGreenWidget, self).__init__(parent=parent)
+ self.green_param_s_spinBox = QDoubleSpinBox()
+ self.green_param_s_spinBox.setMinimum(0)
+ self.green_param_s_spinBox.setSingleStep(0.01)
+ self.green_param_s_spinBox.setMaximum(2)
+ self.green_param_s_spinBox.setObjectName('green_param_s')
+
+ self.green_param_v_spinBox = QDoubleSpinBox()
+ self.green_param_v_spinBox.setMinimum(0)
+ self.green_param_v_spinBox.setSingleStep(0.01)
+ self.green_param_v_spinBox.setMaximum(2)
+ self.green_param_v_spinBox.setObjectName('green_param_v')
+
+ self.setColumnCount(2)
+ self.setRowCount(2)
+ self.setItem(0, 0, QTableWidgetItem('绿色饱和度'))
+ self.setCellWidget(0, 1, self.green_param_v_spinBox)
+ self.setItem(1, 0, QTableWidgetItem('绿色亮度'))
+ self.setCellWidget(1, 1, self.green_param_s_spinBox)
+ self.signal_connect()
+
+
+class HSLCyanWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(HSLCyanWidget, self).__init__(parent=parent)
+ self.cyan_param_s_spinBox = QDoubleSpinBox()
+ self.cyan_param_s_spinBox.setMinimum(0)
+ self.cyan_param_s_spinBox.setSingleStep(0.01)
+ self.cyan_param_s_spinBox.setMaximum(2)
+ self.cyan_param_s_spinBox.setObjectName('cyan_param_s')
+
+ self.cyan_param_v_spinBox = QDoubleSpinBox()
+ self.cyan_param_v_spinBox.setMinimum(0)
+ self.cyan_param_v_spinBox.setSingleStep(0.01)
+ self.cyan_param_v_spinBox.setMaximum(2)
+ self.cyan_param_v_spinBox.setObjectName('cyan_param_v')
+
+ self.setColumnCount(2)
+ self.setRowCount(2)
+ self.setItem(0, 0, QTableWidgetItem('青色饱和度'))
+ self.setCellWidget(0, 1, self.cyan_param_v_spinBox)
+ self.setItem(1, 0, QTableWidgetItem('青色亮度'))
+ self.setCellWidget(1, 1, self.cyan_param_s_spinBox)
+ self.signal_connect()
+
+
+class HSLBlueWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(HSLBlueWidget, self).__init__(parent=parent)
+ self.blue_param_s_spinBox = QDoubleSpinBox()
+ self.blue_param_s_spinBox.setMinimum(0)
+ self.blue_param_s_spinBox.setSingleStep(0.01)
+ self.blue_param_s_spinBox.setMaximum(2)
+ self.blue_param_s_spinBox.setObjectName('blue_param_s')
+
+ self.blue_param_v_spinBox = QDoubleSpinBox()
+ self.blue_param_v_spinBox.setMinimum(0)
+ self.blue_param_v_spinBox.setSingleStep(0.01)
+ self.blue_param_v_spinBox.setMaximum(2)
+ self.blue_param_v_spinBox.setObjectName('blue_param_v')
+
+ self.setColumnCount(2)
+ self.setRowCount(2)
+ self.setItem(0, 0, QTableWidgetItem('蓝色饱和度'))
+ self.setCellWidget(0, 1, self.blue_param_v_spinBox)
+ self.setItem(1, 0, QTableWidgetItem('蓝色亮度'))
+ self.setCellWidget(1, 1, self.blue_param_s_spinBox)
+ self.signal_connect()
+
+
+class HSLPurpleWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(HSLPurpleWidget, self).__init__(parent=parent)
+ self.purple_param_s_spinBox = QDoubleSpinBox()
+ self.purple_param_s_spinBox.setMinimum(0)
+ self.purple_param_s_spinBox.setSingleStep(0.01)
+ self.purple_param_s_spinBox.setMaximum(2)
+ self.purple_param_s_spinBox.setObjectName('purple_param_s')
+
+ self.purple_param_v_spinBox = QDoubleSpinBox()
+ self.purple_param_v_spinBox.setMinimum(0)
+ self.purple_param_v_spinBox.setSingleStep(0.01)
+ self.purple_param_v_spinBox.setMaximum(2)
+ self.purple_param_v_spinBox.setObjectName('purple_param_v')
+
+ self.setColumnCount(2)
+ self.setRowCount(2)
+ self.setItem(0, 0, QTableWidgetItem('紫色饱和度'))
+ self.setCellWidget(0, 1, self.purple_param_v_spinBox)
+ self.setItem(1, 0, QTableWidgetItem('紫色亮度'))
+ self.setCellWidget(1, 1, self.purple_param_s_spinBox)
+ self.signal_connect()
+
+
+class StyleTransformTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(StyleTransformTableWidget, self).__init__(parent=parent)
+
+
+class RotateLeftTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(RotateLeftTableWidget, self).__init__(parent=parent)
+
+
+class RotateRightTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(RotateRightTableWidget, self).__init__(parent=parent)
+
+
+class UpDownTableWidget(TableWidget):
+ def __init__(self, parent=None):
+ super(UpDownTableWidget, self).__init__(parent=parent)
\ No newline at end of file
diff --git a/custom/treeView.py b/custom/treeView.py
new file mode 100644
index 0000000..52c31f1
--- /dev/null
+++ b/custom/treeView.py
@@ -0,0 +1,35 @@
+import cv2
+import numpy as np
+from PyQt5.QtWidgets import *
+from PyQt5.QtCore import *
+
+
+class FileSystemTreeView(QTreeView, QDockWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.mainwindow = parent
+ self.fileSystemModel = QFileSystemModel()
+ self.fileSystemModel.setRootPath('.')
+ self.setModel(self.fileSystemModel)
+ # 隐藏size,date等列
+ self.setColumnWidth(0, 200)
+ self.setColumnHidden(1, True)
+ self.setColumnHidden(2, True)
+ self.setColumnHidden(3, True)
+ # 不显示标题栏
+ self.header().hide()
+ # 设置动画
+ self.setAnimated(True)
+ # 选中不显示虚线
+ self.setFocusPolicy(Qt.NoFocus)
+ self.doubleClicked.connect(self.select_image)
+ self.setMinimumWidth(200)
+
+ def select_image(self, file_index):
+ file_name = self.fileSystemModel.filePath(file_index)
+ if file_name.endswith(('.jpg', '.png', '.bmp')):
+ src_img = cv2.imdecode(np.fromfile(file_name, dtype=np.uint8), -1)
+ self.mainwindow.change_image(src_img)
+
+
+
diff --git a/custom/treeWidgets.py b/custom/treeWidgets.py
new file mode 100644
index 0000000..d5ac2e6
--- /dev/null
+++ b/custom/treeWidgets.py
@@ -0,0 +1,74 @@
+from PyQt5.QtGui import *
+from PyQt5.QtCore import *
+from PyQt5.QtWidgets import *
+
+from config import items
+
+
+class MyTreeWidget(QTreeWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.mainwindow = parent
+ self.setDragEnabled(True)
+ # 选中不显示虚线
+ # self.setEditTriggers(QAbstractItemView.NoEditTriggers)
+ self.setFocusPolicy(Qt.NoFocus)
+
+
+class FuncTreeWidget(QTreeWidget):
+ def __init__(self, parent=None):
+ super(FuncTreeWidget, self).__init__(parent)
+
+ self.mainwindow = parent
+ # 根节点
+ root1 = QTreeWidgetItem(self)
+ root1.setText(0, '重构') # 0代表第一列,即Key列
+ root1.setIcon(0, QIcon('icons/color.png')) # 为节点设置图标
+ self.setColumnWidth(0, 200) # 第一列列宽设为200
+ self.header().hide()
+ self.itemClicked.connect(self.function)
+
+ # 添加子节点1
+ child1 = QTreeWidgetItem(root1)
+ child1.setText(0, '裁剪')
+ child1.setIcon(0, QIcon('icons/color.png'))
+
+ root2 = QTreeWidgetItem(self)
+ root2.setText(0, '调整') # 第一列Key为 子节点1
+ root2.setIcon(0, QIcon('icons/color.png'))
+
+ child4 = QTreeWidgetItem(root2)
+ child4.setText(0, '光效')
+ child4.setIcon(0, QIcon('icons/color.png'))
+
+ child5 = QTreeWidgetItem(root2)
+ child5.setText(0, '色彩')
+ child5.setIcon(0, QIcon('icons/color.png'))
+
+ child6 = QTreeWidgetItem(root2)
+ child6.setText(0, 'HSL')
+ child6.setIcon(0, QIcon('icons/color.png'))
+
+ child8 = QTreeWidgetItem(root2)
+ child8.setText(0, '质感')
+ child8.setIcon(0, QIcon('icons/color.png'))
+
+ child10 = QTreeWidgetItem(root2)
+ child10.setText(0, '特效')
+ child10.setIcon(0, QIcon('icons/color.png'))
+
+ root3 = QTreeWidgetItem(self)
+ root3.setText(0, '风格迁移')
+ root3.setIcon(0, QIcon('icons/color.png'))
+
+ root4 = QTreeWidgetItem(self)
+ root4.setText(0, '其他操作')
+ root4.setIcon(0, QIcon('icons/color.png'))
+
+ # 默认所有节点都处于展开状态
+ # self.expandAll()
+
+ def function(self):
+ func_item = self.currentItem()
+ self.mainwindow.update_dock(func_item.text(0))
+
diff --git a/flags.py b/flags.py
new file mode 100644
index 0000000..fbd4a70
--- /dev/null
+++ b/flags.py
@@ -0,0 +1,96 @@
+import cv2
+
+GRAYING_STACKED_WIDGET = 0
+FILTER_STACKED_WIDGET = 1
+MORPH_STACKED_WIDGET = 2
+GRAD_STACKED_WIDGET = 3
+THRESH_STACKED_WIDGET = 4
+EDGE_STACKED_WIDGET = 5
+
+BGR2GRAY_COLOR = 0
+GRAY2BGR_COLOR = 1
+COLOR = {
+ BGR2GRAY_COLOR: cv2.COLOR_BGR2GRAY,
+ GRAY2BGR_COLOR: cv2.COLOR_GRAY2BGR
+}
+
+MEAN_FILTER = 0
+GAUSSIAN_FILTER = 1
+MEDIAN_FILTER = 2
+
+ERODE_MORPH_OP = 0
+DILATE_MORPH_OP = 1
+OPEN_MORPH_OP = 2
+CLOSE_MORPH_OP = 3
+GRADIENT_MORPH_OP = 4
+TOPHAT_MORPH_OP = 5
+BLACKHAT_MORPH_OP = 6
+
+MORPH_OP = {
+ ERODE_MORPH_OP: cv2.MORPH_ERODE,
+ DILATE_MORPH_OP: cv2.MORPH_DILATE,
+ OPEN_MORPH_OP: cv2.MORPH_OPEN,
+ CLOSE_MORPH_OP: cv2.MORPH_CLOSE,
+ GRADIENT_MORPH_OP: cv2.MORPH_GRADIENT,
+ TOPHAT_MORPH_OP: cv2.MORPH_TOPHAT,
+ BLACKHAT_MORPH_OP: cv2.MORPH_BLACKHAT
+}
+
+RECT_MORPH_SHAPE = 0
+CROSS_MORPH_SHAPE = 1
+ELLIPSE_MORPH_SHAPE = 2
+
+MORPH_SHAPE = {
+ RECT_MORPH_SHAPE: cv2.MORPH_RECT,
+ CROSS_MORPH_SHAPE: cv2.MORPH_CROSS,
+ ELLIPSE_MORPH_SHAPE: cv2.MORPH_ELLIPSE
+}
+
+SOBEL_GRAD = 0
+SCHARR_GRAD = 1
+LAPLACIAN_GRAD = 2
+
+BINARY_THRESH_METHOD = 0
+BINARY_INV_THRESH_METHOD = 1
+TRUNC_THRESH_METHOD = 2
+TOZERO_THRESH_METHOD = 3
+TOZERO_INV_THRESH_METHOD = 4
+OTSU_THRESH_METHOD = 5
+THRESH_METHOD = {
+ BINARY_THRESH_METHOD: cv2.THRESH_BINARY, # 0
+ BINARY_INV_THRESH_METHOD: cv2.THRESH_BINARY_INV, # 1
+ TRUNC_THRESH_METHOD: cv2.THRESH_TRUNC, # 2
+ TOZERO_THRESH_METHOD: cv2.THRESH_TOZERO, # 3
+ TOZERO_INV_THRESH_METHOD: cv2.THRESH_TOZERO_INV, # 4
+ OTSU_THRESH_METHOD: cv2.THRESH_OTSU # 5
+}
+
+EXTERNAL_CONTOUR_MODE = 0
+LIST_CONTOUR_MODE = 1
+CCOMP_CONTOUR_MODE = 2
+TREE_CONTOUR_MODE = 3
+CONTOUR_MODE = {
+ EXTERNAL_CONTOUR_MODE: cv2.RETR_EXTERNAL,
+ LIST_CONTOUR_MODE: cv2.RETR_LIST,
+ CCOMP_CONTOUR_MODE: cv2.RETR_CCOMP,
+ TREE_CONTOUR_MODE: cv2.RETR_TREE
+}
+
+NONE_CONTOUR_METHOD = 0
+SIMPLE_CONTOUR_METHOD = 1
+CONTOUR_METHOD = {
+ NONE_CONTOUR_METHOD: cv2.CHAIN_APPROX_NONE,
+ SIMPLE_CONTOUR_METHOD: cv2.CHAIN_APPROX_SIMPLE
+}
+
+NORMAL_CONTOUR = 0
+RECT_CONTOUR = 1
+MINRECT_CONTOUR = 2
+MINCIRCLE_CONTOUR = 3
+
+
+# 均衡化
+BLUE_CHANNEL = 0
+GREEN_CHANNEL = 1
+RED_CHANNEL = 2
+ALL_CHANNEL = 3
diff --git a/icons/branch-close.png b/icons/branch-close.png
new file mode 100644
index 0000000..1a54719
Binary files /dev/null and b/icons/branch-close.png differ
diff --git a/icons/branch-open.png b/icons/branch-open.png
new file mode 100644
index 0000000..5b733fd
Binary files /dev/null and b/icons/branch-open.png differ
diff --git a/icons/color.png b/icons/color.png
new file mode 100644
index 0000000..e6be09f
Binary files /dev/null and b/icons/color.png differ
diff --git a/icons/main.png b/icons/main.png
new file mode 100644
index 0000000..c0dbddd
Binary files /dev/null and b/icons/main.png differ
diff --git a/icons/右旋转.png b/icons/右旋转.png
new file mode 100644
index 0000000..e845a3e
Binary files /dev/null and b/icons/右旋转.png differ
diff --git a/icons/左旋转.png b/icons/左旋转.png
new file mode 100644
index 0000000..4cac983
Binary files /dev/null and b/icons/左旋转.png differ
diff --git a/icons/直方图.png b/icons/直方图.png
new file mode 100644
index 0000000..81e507d
Binary files /dev/null and b/icons/直方图.png differ
diff --git a/style/candy.t7 b/style/candy.t7
new file mode 100644
index 0000000..69e37b1
Binary files /dev/null and b/style/candy.t7 differ
diff --git a/style/composition_vii.t7 b/style/composition_vii.t7
new file mode 100644
index 0000000..0201669
Binary files /dev/null and b/style/composition_vii.t7 differ
diff --git a/style/feathers.t7 b/style/feathers.t7
new file mode 100644
index 0000000..69c192d
Binary files /dev/null and b/style/feathers.t7 differ
diff --git a/style/la_muse.t7 b/style/la_muse.t7
new file mode 100644
index 0000000..b8176a7
Binary files /dev/null and b/style/la_muse.t7 differ
diff --git a/style/mosaic.t7 b/style/mosaic.t7
new file mode 100644
index 0000000..44aa0a1
Binary files /dev/null and b/style/mosaic.t7 differ
diff --git a/style/starry_night.t7 b/style/starry_night.t7
new file mode 100644
index 0000000..78a8e78
Binary files /dev/null and b/style/starry_night.t7 differ
diff --git a/style/the_scream.t7 b/style/the_scream.t7
new file mode 100644
index 0000000..f5e5736
Binary files /dev/null and b/style/the_scream.t7 differ
diff --git a/style/the_wave.t7 b/style/the_wave.t7
new file mode 100644
index 0000000..73af44b
Binary files /dev/null and b/style/the_wave.t7 differ
diff --git a/style/udnie.t7 b/style/udnie.t7
new file mode 100644
index 0000000..6249ef3
Binary files /dev/null and b/style/udnie.t7 differ
diff --git a/tmp.jpg b/tmp.jpg
new file mode 100644
index 0000000..fbec5e5
Binary files /dev/null and b/tmp.jpg differ