You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

990 lines
42 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import Qt.labs.platform
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Material
import QtQuick.Layouts
import QtQuick.Dialogs
import "Components"
import Util 1.0
ApplicationWindow {
visibility: "Maximized"
visible: true
title: qsTr("图像处理工具")
Material.theme: Material.Dark
Material.accent: Material.LightBlue
menuBar: MenuBar {
FileDialog {
id: openDialog
title: qsTr("打开图片")
nameFilters: ["图片文件 (*.jpg *.png)"]
onAccepted: {
imageItem.readFile(selectedFile)
}
}
FileDialog {
id: saveDialog
title: qsTr("保存图片")
fileMode: FileDialog.SaveFile
nameFilters: ["图片文件 (*.jpg *.png)"]
onAccepted: {
imageItem.saveFile(selectedFile)
}
}
Menu {
title: qsTr("文件")
Action {
text: qsTr("打开")
onTriggered: {
openDialog.open()
}
}
Action {
text: qsTr("保存")
onTriggered: {
saveDialog.open()
}
}
}
Menu {
title: qsTr("操作")
Action {
text: qsTr("撤销")
onTriggered: {
imageItem.withdraw()
}
}
}
}
Pane {
anchors.fill: parent
RowLayout {
anchors.fill: parent
spacing: 25
ListView {
id: tab
Layout.fillHeight: true
Layout.preferredWidth: contentItem.childrenRect.width
currentIndex: 0
spacing: 10
model: ["图像变换", "图形绘制", "灰度变换", "边缘检测", "图像平滑", "形态处理", "噪声添加", "风格迁移"]
delegate: TabButton {
text: qsTr(modelData)
checked: tab.currentIndex === index
onClicked: {
tab.currentIndex = index
}
}
Pane {
z: -1
anchors.fill: parent
Material.elevation: 8
}
}
ImageItem {
id: imageItem
Layout.fillHeight: true
Layout.fillWidth: true
Pane {
z: -1
anchors.fill: parent
Material.elevation: 8
}
MouseArea {
id: imageItemArea
anchors.fill: parent
property int ix
property int iy
property bool isSelecting: false
signal select(point point)
onPressed: {
if (isSelecting) {
return
}
cursorShape = Qt.ClosedHandCursor
ix = mouseX
iy = mouseY
}
onReleased: {
if (isSelecting) {
return
}
cursorShape = Qt.ArrowCursor
}
onPositionChanged: {
if (isSelecting) {
return
}
if (pressed) {
parent.moveBy(ix - mouseX, iy - mouseY)
}
ix = mouseX
iy = mouseY
}
onClicked: {
if (isSelecting) {
const point = imageItem.getPoint(mouseX, mouseY)
select(point)
}
imageItemArea.isSelecting = false
}
}
}
Pane {
Material.elevation: 8
Layout.fillHeight: true
Layout.preferredWidth: 250
StackLayout {
anchors.fill: parent
currentIndex: tab.currentIndex
Section {
Operation {
title: qsTr("消除通道")
Labelrow {
text: qsTr("通道")
ComboBox {
id: removeChannel_channel
model: ["r", "g", "b"]
}
}
onSubmitted: {
imageItem.removeChannel(
removeChannel_channel.currentIndex)
}
}
Operation {
title: qsTr("平移")
Labelrow {
text: qsTr("左右")
Floatspin {
id: translation_dx
from: -1000
to: 1000
decimals: 0
stepSize: 1
defaultValue: 0
}
}
Labelrow {
text: qsTr("上下")
Floatspin {
id: translation_dy
from: -1000
to: 1000
decimals: 0
stepSize: 1
defaultValue: 0
}
}
Labelrow {
text: qsTr("填充")
Selectcolor {
id: translation_border
}
}
onSubmitted: {
imageItem.translation(translation_dx.value,
translation_dy.value,
translation_border.color)
}
}
Operation {
title: qsTr("旋转")
Labelrow {
text: qsTr("模式")
ComboBox {
id: rotation_combobox
model: ["中心旋转", "直角旋转"]
}
}
StackLayout {
Layout.fillWidth: true
currentIndex: rotation_combobox.currentIndex
Labelrow {
text: qsTr("角度")
Floatspin {
Layout.fillWidth: true
id: centralRotation_theta
from: 0
to: 360
decimals: 0
stepSize: 1
}
}
Labelrow {
text: qsTr("方式")
ComboBox {
id: rightAngleRotation_theta
model: ["不旋转", "顺时针90°", "180°", "逆时针90°"]
}
}
}
onSubmitted: {
switch (rotation_combobox.currentIndex) {
case 0:
imageItem.centralRotation(
centralRotation_theta.value)
break
case 1:
imageItem.rightAngleRotation(
rightAngleRotation_theta.currentIndex)
break
}
}
}
Operation {
title: qsTr("翻转")
Labelrow {
text: qsTr("模式")
ComboBox {
id: flip_combobox
model: ["不翻转", "垂直翻转", "水平翻转", "水平垂直翻转"]
}
}
onSubmitted: {
imageItem.flip(flip_combobox.currentIndex)
}
}
Operation {
title: qsTr("缩放")
Labelrow {
text: qsTr("宽度")
Floatspin {
id: resize_width_size
from: 0.01
to: 3.00
decimals: 2
}
}
Labelrow {
text: qsTr("高度")
Floatspin {
id: resize_height_size
from: 0.01
to: 3.00
decimals: 2
}
}
onSubmitted: {
imageItem.resize(resize_width_size.value,
resize_height_size.value)
}
}
Operation {
title: qsTr("仿射变换")
onSubmitted: {
imageItem.affine()
}
}
Operation {
title: qsTr("错切")
onSubmitted: {
imageItem.shear()
}
}
Operation {
title: qsTr("投影变换")
onSubmitted: {
imageItem.projective()
}
}
}
Section {
Operation {
title: qsTr("直线")
Labelrow {
text: qsTr("起点")
Selectpoint {
id: line_start
area: imageItemArea
}
}
Labelrow {
text: qsTr("终点")
Selectpoint {
id: line_end
area: imageItemArea
}
}
Labelrow {
text: qsTr("颜色")
Selectcolor {
id: line_color
}
}
Labelrow {
text: qsTr("线宽")
Floatspin {
id: line_width
from: 1
to: 10
decimals: 0
}
}
onSubmitted: {
imageItem.line(line_start.point,
line_end.point,
line_color.color,
line_width.value)
}
}
Operation {
title: qsTr("矩形")
Labelrow {
text: qsTr("顶点")
Selectpoint {
id: rectangle_start
area: imageItemArea
}
}
Labelrow {
text: qsTr("对顶点")
Selectpoint {
id: rectangle_end
area: imageItemArea
}
}
Labelrow {
text: qsTr("颜色")
Selectcolor {
id: rectangle_color
}
}
Labelrow {
text: qsTr("线宽")
Floatspin {
id: rectangle_width
from: 1
to: 10
decimals: 0
}
}
onSubmitted: {
imageItem.rectangle(rectangle_start.point,
rectangle_end.point,
rectangle_color.color,
rectangle_width.value)
}
}
Operation {
title: qsTr("圆形")
Labelrow {
text: qsTr("圆心")
Selectpoint {
id: circle_center
area: imageItemArea
}
}
Labelrow {
text: qsTr("圆上一点")
Selectpoint {
id: circle_side
area: imageItemArea
}
}
Labelrow {
text: qsTr("颜色")
Selectcolor {
id: circle_color
}
}
Labelrow {
text: qsTr("线宽")
Floatspin {
id: circle_width
from: 1
to: 10
decimals: 0
}
}
onSubmitted: {
imageItem.circle(circle_center.point,
circle_side.point,
circle_color.color,
circle_width.value)
}
}
Operation {
title: qsTr("文字")
Labelrow {
text: qsTr("左下角")
Selectpoint {
id: text_start
area: imageItemArea
}
}
Labelrow {
text: qsTr("颜色")
Selectcolor {
id: text_color
}
}
Labelrow {
text: qsTr("字号")
Floatspin {
id: text_fontsize
from: 1
to: 10
decimals: 0
defaultValue: 4
}
}
Labelrow {
text: qsTr("线宽")
Floatspin {
id: text_width
from: 1
to: 10
decimals: 0
}
}
Labelrow {
text: qsTr("内容")
TextField {
id: text_text
validator: RegularExpressionValidator {
regularExpression: /[0-9A-Za-z]+/
}
}
}
onSubmitted: {
imageItem.text(text_start.point,
text_color.color,
text_fontsize.value,
text_width.value, text_text.text)
}
}
}
Section {
Operation {
title: qsTr("二值化")
Labelrow {
text: qsTr("阈值")
Floatspin {
id: binaryTransformation_thresh
from: 0
to: 255
decimals: 0
defaultValue: 100
}
}
onSubmitted: {
imageItem.binaryTransformation(
binaryTransformation_thresh.value)
}
}
Operation {
title: qsTr("分段线性变换")
onSubmitted: {
imageItem.linearGrayscaleTransformation()
}
}
Operation {
title: qsTr("灰度级分层")
Labelrow {
text: qsTr("下界")
Floatspin {
id: grayLayered_low_thresh
from: 0
to: 255
decimals: 0
defaultValue: 45
}
}
Labelrow {
text: qsTr("上界")
Floatspin {
id: grayLayered_high_thresh
from: grayLayered_low_thresh.value
to: 255
decimals: 0
defaultValue: 155
}
}
onSubmitted: {
imageItem.grayLayered(
grayLayered_low_thresh.value,
grayLayered_high_thresh.value)
}
}
Operation {
title: qsTr("对数变换")
onSubmitted: {
imageItem.logTrans()
}
}
Operation {
title: qsTr("幂律变换")
Labelrow {
text: qsTr("γ")
Floatspin {
id: gammaTrans_gamma
from: 0.01
to: 25
decimals: 2
defaultValue: 2
}
}
onSubmitted: {
imageItem.gammaTrans(gammaTrans_gamma.value)
}
}
Operation {
title: qsTr("灰度直方图")
onSubmitted: {
imageItem.grayHistogram()
}
}
}
Section {
Operation {
title: qsTr("基本算子")
Labelrow {
text: qsTr("算子")
ComboBox {
id: edgeProcessing_operator
model: ["Roberts", "Sobel", "Prewitt", "Laplacian"]
}
}
onSubmitted: {
switch (edgeProcessing_operator.currentIndex) {
case 0:
imageItem.roberts()
break
case 1:
imageItem.sobel()
break
case 2:
imageItem.prewitt()
break
case 3:
imageItem.laplacian()
break
}
}
}
Operation {
title: qsTr("LoG算子")
Labelrow {
text: qsTr("卷积核")
Floatspin {
id: loG_size
from: 3
to: 7
decimals: 0
}
}
Labelrow {
text: qsTr("σ")
Floatspin {
id: loG_sigma
from: 0.01
to: 25
decimals: 2
defaultValue: 0.8
}
}
onSubmitted: {
imageItem.loG(loG_size.value, loG_sigma.value)
}
}
Operation {
title: "Canny算子"
Labelrow {
text: qsTr("卷积核")
Floatspin {
id: canny_size
from: 3
to: 7
decimals: 0
defaultValue: 5
}
}
Labelrow {
text: qsTr("下界")
Floatspin {
id: canny_low_thresh
from: 0
to: 255
decimals: 0
defaultValue: 50
}
}
Labelrow {
text: qsTr("上界")
Floatspin {
id: canny_high_thresh
from: canny_low_thresh.value
to: 255
decimals: 0
defaultValue: 150
}
}
onSubmitted: {
imageItem.canny(canny_size.value,
canny_low_thresh.value,
canny_high_thresh.value)
}
}
}
Section {
Operation {
title: qsTr("空域平滑")
Labelrow {
text: qsTr("算法")
ComboBox {
id: smoothSpace
model: ["均值滤波", "中值滤波"]
}
}
StackLayout {
Layout.fillWidth: true
currentIndex: smoothSpace.currentIndex
Labelrow {
text: qsTr("卷积核")
Floatspin {
id: blur_size
from: 3
to: 7
decimals: 0
}
}
Labelrow {
text: qsTr("卷积核")
Floatspin {
id: medianBlur_size
from: 3
to: 7
decimals: 0
}
}
}
onSubmitted: {
switch (smoothSpace.currentIndex) {
case 0:
imageItem.blur(blur_size.value)
break
case 1:
imageItem.medianBlur(medianBlur_size.value)
break
}
}
}
Operation {
title: qsTr("频域平滑")
Labelrow {
text: qsTr("算法")
ComboBox {
id: smoothFrequency
model: ["理想低通滤波", "巴特沃斯滤波", "高斯滤波"]
}
}
StackLayout {
currentIndex: smoothFrequency.currentIndex
Layout.fillWidth: true
Layout.preferredHeight: children[currentIndex].height
Labelrow {
Layout.fillHeight: false
text: qsTr("D0")
Floatspin {
id: lowPassIdealBlur_d0
from: 1
to: 2000
decimals: 0
defaultValue: 20
}
}
ColumnLayout {
Layout.fillHeight: false
Labelrow {
text: qsTr("D0")
Floatspin {
id: lowPassButterworthBlur_d0
from: 1
to: 200
decimals: 0
defaultValue: 20
}
}
Labelrow {
text: qsTr("n")
Floatspin {
id: lowPassButterworthBlur_n
from: 1
to: 10
decimals: 0
defaultValue: 2
}
}
}
Labelrow {
Layout.fillHeight: false
text: qsTr("D0")
Floatspin {
id: lowPassGaussianBlur_d0
from: 1
to: 200
decimals: 0
defaultValue: 20
}
}
}
onSubmitted: {
switch (smoothFrequency.currentIndex) {
case 0:
imageItem.lowPassIdealBlur(
lowPassIdealBlur_d0.value)
break
case 1:
imageItem.lowPassButterworthBlur(
lowPassButterworthBlur_d0.value,
lowPassButterworthBlur_n.value)
break
case 2:
imageItem.lowPassGaussianBlur(
lowPassGaussianBlur_d0.value)
break
}
}
}
}
Section {
Operation {
title: qsTr("腐蚀")
Labelrow {
text: qsTr("形状")
ComboBox {
id: erode_shape
model: ["矩形", "十字", "椭圆"]
}
}
Labelrow {
text: qsTr("大小")
Floatspin {
id: erode_size
from: 3
to: 7
decimals: 0
defaultValue: 5
}
}
onSubmitted: {
imageItem.erode(erode_shape.currentIndex,
erode_size.value)
}
}
Operation {
title: qsTr("膨胀")
Labelrow {
text: qsTr("形状")
ComboBox {
id: dilate_shape
model: ["矩形", "十字", "椭圆"]
}
}
Labelrow {
text: qsTr("大小")
Floatspin {
id: dilate_size
from: 3
to: 7
decimals: 0
defaultValue: 5
}
}
onSubmitted: {
imageItem.dilate(dilate_shape.currentIndex,
dilate_size.value)
}
}
Operation {
title: qsTr("开运算")
Labelrow {
text: qsTr("形状")
ComboBox {
id: open_shape
model: ["矩形", "十字", "椭圆"]
}
}
Labelrow {
text: qsTr("大小")
Floatspin {
id: open_size
from: 3
to: 7
decimals: 0
defaultValue: 5
}
}
onSubmitted: {
imageItem.open(open_shape.currentIndex,
open_size.value)
}
}
Operation {
title: qsTr("闭运算")
Labelrow {
text: qsTr("形状")
ComboBox {
id: close_shape
model: ["矩形", "十字", "椭圆"]
}
}
Labelrow {
text: qsTr("大小")
Floatspin {
id: close_size
from: 3
to: 7
decimals: 0
defaultValue: 5
}
}
onSubmitted: {
imageItem.close(close_shape.currentIndex,
close_size.value)
}
}
}
Section {
Operation {
title: qsTr("高斯噪声")
Labelrow {
text: qsTr("μ")
Floatspin {
id: gaussNoise_mu
from: 0.0
to: 10.0
decimals: 1
}
}
Labelrow {
text: qsTr("σ")
Floatspin {
id: gaussNoise_sigma
from: 0.0
to: 25.0
decimals: 1
defaultValue: 20.0
}
}
onSubmitted: {
imageItem.gaussNoise(gaussNoise_mu.value,
gaussNoise_sigma.value)
}
}
Operation {
title: qsTr("指数噪声")
Labelrow {
text: qsTr("a")
Floatspin {
id: expNoise_a
from: 0.0
to: 25.0
decimals: 1
defaultValue: 10.0
}
}
onSubmitted: {
imageItem.expNoise(expNoise_a.value)
}
}
Operation {
title: qsTr("平均噪声")
Labelrow {
text: qsTr("均值")
Floatspin {
id: uniformNoise_mean
from: 0
to: 20
decimals: 0
defaultValue: 10
}
}
Labelrow {
text: qsTr("σ")
Floatspin {
id: uniformNoise_sigma
from: 0
to: 500
decimals: 0
defaultValue: 100
}
}
onSubmitted: {
imageItem.uniformNoise(uniformNoise_mean.value,
uniformNoise_sigma.value)
}
}
Operation {
title: qsTr("椒盐噪声")
Labelrow {
text: qsTr("盐概率")
Floatspin {
id: pepperSaltNoise_ps
from: 0.00
to: 1.00
decimals: 2
defaultValue: 0.05
}
}
Labelrow {
text: qsTr("椒概率")
Floatspin {
id: pepperSaltNoise_pp
from: 0.00
to: 1.00 - pepperSaltNoise_ps.value
decimals: 2
defaultValue: 0.02
}
}
onSubmitted: {
imageItem.pepperSaltNoise(
pepperSaltNoise_ps.value,
pepperSaltNoise_pp.value)
}
}
}
Section {
Operation {
title: qsTr("风格迁移")
Labelrow {
text: qsTr("选择风格")
ComboBox {
id: styleTransfer_style
textRole: "key"
valueRole: "value"
model: ListModel {
ListElement {
key: "星月夜"
value: "starrynew"
}
ListElement {
key: "电路"
value: "circuit"
}
ListElement {
key: "海洋"
value: "ocean"
}
ListElement {
key: "宇宙"
value: "stars"
}
}
}
}
onSubmitted: {
imageItem.styleTransfer(
styleTransfer_style.currentValue)
}
}
}
}
}
}
}
}