《基於qml創建最簡單的圖像處理程序》系列課程及配套代碼
基於qml創建最簡單的圖像處理程序(1)-基於qml創建界面
http://www.cnblogs.com/jsxyhelu/p/8343310.html
課程1附件
https://files.cnblogs.com/files/jsxyhelu/%E9%98%B6%E6%AE%B5%E4%BB%A3%E7%A0%811.zip
基於qml創建最簡單的圖像處理程序(2)-使用c++&qml進行圖像處理
http://www.cnblogs.com/jsxyhelu/p/8361441.html
課程2附件
https://files.cnblogs.com/files/jsxyhelu/%E9%98%B6%E6%AE%B5%E4%BB%A3%E7%A0%812.zip
基於qml創建最簡單的圖像處理程序(3)-使用opencv&qml進行圖像處理
http://www.cnblogs.com/jsxyhelu/p/8361443.html
課程3附件
https://files.cnblogs.com/files/jsxyhelu/%E9%98%B6%E6%AE%B5%E4%BB%A3%E7%A0%813.zip
為什么使用QT,包括進一步使用QML?兩個主要原因,一是因為我是一個c++程序員,有語言使用慣性;二是我主要做圖像處理方面工作,使用什么平台對於我來說不重要,我只需要在不同平台上面能夠運行我的圖像處理程序(而主要是和OpenCV有關系的)。所以選擇QT,它能夠在win/linux/android,包括PI上面都提供不錯的GUI支持;而如果我想在Android上編寫圖像處理程序,又主要遇到兩個問題,一是相機的獲取。OpenCV的videocapture在Android上支持不好,在最新版本的OpenCV里面已經把這個部分相關內容去掉了,同時QCamera(基於widget的camera)支持也不好,Qml是目前對Android支持最好的。這個地方QML提供的camera功能就類似windows中的dshow一樣,是一個基礎類庫;二是界面的創建,在windows下面,基於ribbon等,我能夠創建還說的過去的界面,但是在Android中,目前沒有很好的工具。特別是在手機這個小小界面中,如果界面有問很影響使用。
import QtQuick.Window 2. 2
Window {
visible : true
width : 640
height : 480
}
import QtQuick.Window 2. 2
import QtQuick.Controls 1. 1
import QtQuick.Dialogs 1. 1
import QtQuick.Controls.Styles 1. 1
Window {
visible : true
width : 640
height : 480
//RGB
color : "#0000FF";
//忙等控件,包含在QtQuick.Controls中
BusyIndicator {
id : busy;
running : false;
anchors.centerIn : parent;
z : 2;
}
//狀態顯示Label
Label {
id : stateLabel;
visible : false;
anchors.centerIn : parent;
}
//主要界面
Image {
objectName : "imageViewer";
id : imageViewer;
asynchronous : true;
anchors.fill : parent;
fillMode : Image.PreserveAspectFit;
//根據imageviewer狀態判斷,控制控件表現出不同狀態
onStatusChanged : {
if (imageViewer.status == = Image.Loading) {
busy.running = true;
stateLabel.visible = false;
}
else if(imageViewer.status == = Image.Ready){
busy.running = false;
}
else if(imageViewer.status == = Image.Error){
busy.running = false;
stateLabel.visible = true;
stateLabel.text = "ERROR";
}
}
}
//打開文件界面,包含在 QtQuick.Dialogs 中。固然在Android中使用這個方法打開圖片不是最佳方法,但是可用方法
FileDialog {
id : fileDialog;
title : "Please choose a file";
nameFilters : [ "Image Files (*.jpg *.png *.gif)"];
onAccepted : {
console.log(fileDialog.fileUrl);
imageViewer.source = fileDialog.fileUrl;
}
}
//以下用於創建button,其中ButtonStyle來自QtQuick.Controls.Styles
//其中所謂Component就是可重用構建的意思,這個用於Button的Componet是可以復用的
Component{
id : btnStyle;
ButtonStyle {
background : Rectangle {
implicitWidth : 140;
implicitHeight : 50;
border.width : control.pressed ? 2 : 1;
border.color : (control.pressed || control.hovered) ? "#00A060" : "#888888";
radius : 12;
gradient : Gradient {
GradientStop { position : 0 ; color : control.pressed ? "#cccccc" : "#e0e0e0"; }
GradientStop { position : 1 ; color : control.pressed ? "#aaa" : "#ccc"; }
}
}
}
}
//就是做了個黑色的框子,用於放button的
Rectangle {
anchors.left : parent.left;
anchors.top : parent.top;
anchors.bottom : openFile.bottom;
anchors.bottomMargin : - 6;
anchors.right : quit.right;
anchors.rightMargin : - 6;
color : "#404040";
opacity : 0. 7;
}
//打開按鈕
Button {
id : openFile;
text : "打開";
anchors.left : parent.left;
anchors.leftMargin : 6;
anchors.top : parent.top;
anchors.topMargin : 6;
onClicked : {
fileDialog.visible = true;
}
//直接使用了btnStyle
style : btnStyle;
z : 1;
}
//退出就是退出
Button {
id : quit;
text : "退出";
anchors.left : openFile.right;
anchors.leftMargin : 4;
anchors.bottom : openFile.bottom;
onClicked : {
Qt.quit()
}
style : btnStyle;
z : 1;
}
//另外一個黑色框子,注意用到了op,也就是上面的4個按鈕
Rectangle {
anchors.left : parent.left;
anchors.top : op.top;
anchors.topMargin : - 4;
anchors.bottom : parent.bottom;
anchors.right : op.right;
anchors.rightMargin : - 4;
color : "#404040";
opacity : 0. 7;
}
//以另一種方式將幾個按鈕連在一起
//我們實現4個比較簡單的效果
Grid {
id : op;
anchors.left : parent.left;
anchors.leftMargin : 4;
anchors.bottom : parent.bottom;
anchors.bottomMargin : 4;
rows : 2;
columns : 2;
rowSpacing : 4;
columnSpacing : 4;
z : 1;
//柔化效果
Button {
text : "柔化";
style : btnStyle;
onClicked : {
//busy.running = true;
//processor.process(fileDialog.fileUrl, ImageProcessor.Soften);
}
}
//灰度效果
Button {
text : "灰度";
style : btnStyle;
onClicked : {
//busy.running = true;
//processor.process(fileDialog.fileUrl, ImageProcessor.Gray);
}
}
//浮雕效果
Button {
text : "浮雕";
style : btnStyle;
onClicked : {
//busy.running = true;
//processor.process(fileDialog.fileUrl, ImageProcessor.Emboss);
}
}
//黑白效果
Button {
text : "黑白";
style : btnStyle;
onClicked : {
//busy.running = true;
//processor.process(fileDialog.fileUrl, ImageProcessor.Binarize);
}
}
}
}
visible : true
width : 640
height : 480
//RGB
color : "#0000FF";
……
//忙等控件,包含在QtQuick.Controls中
BusyIndicator {
id : busy;
running : false;
anchors.centerIn : parent;
z : 2;
}
//狀態顯示Label
Label {
id : stateLabel;
visible : false;
anchors.centerIn : parent;
}
//主要圖片顯示
Image {
objectName : "imageViewer";
id : imageViewer;
asynchronous : true;
anchors.fill : parent;
fillMode : Image.PreserveAspectFit;
//根據imageviewer狀態判斷,控制控件表現出不同狀態
onStatusChanged : {
if (imageViewer.status == = Image.Loading) {
busy.running = true;
stateLabel.visible = false;
}
else if(imageViewer.status == = Image.Ready){
busy.running = false;
}
else if(imageViewer.status == = Image.Error){
busy.running = false;
stateLabel.visible = true;
stateLabel.text = "ERROR";
}
}
}
//打開文件界面,包含在 QtQuick.Dialogs 中。固然在Android中使用這個方法打開圖片不是最佳方法,但是可用方法
FileDialog {
id : fileDialog;
title : "Please choose a file";
nameFilters : [ "Image Files (*.jpg *.png *.gif)"];
onAccepted : {
console.log(fileDialog.fileUrl);
imageViewer.source = fileDialog.fileUrl;
}
}
//以下用於創建button,其中ButtonStyle來自QtQuick.Controls.Styles
//其中所謂Component就是可重用構建的意思,這個用於Button的Componet是可以復用的
Component{
id : btnStyle;
ButtonStyle {
background : Rectangle {
implicitWidth : 140;
implicitHeight : 50;
border.width : control.pressed ? 2 : 1;
border.color : (control.pressed || control.hovered) ? "#00A060" : "#888888";
radius : 12;
gradient : Gradient {
GradientStop { position : 0 ; color : control.pressed ? "#cccccc" : "#e0e0e0"; }
GradientStop { position : 1 ; color : control.pressed ? "#aaa" : "#ccc"; }
}
}
}
}
//打開按鈕
Button {
id : openFile;
text : "打開";
anchors.left : parent.left;
anchors.leftMargin : 6;
anchors.top : parent.top;
anchors.topMargin : 6;
onClicked : {
fileDialog.visible = true;
}
//直接使用了btnStyle
style : btnStyle;
z : 1;
}
//退出就是退出
Button {
id : quit;
text : "退出";
anchors.left : openFile.right;
anchors.leftMargin : 4;
anchors.bottom : openFile.bottom;
onClicked : {
Qt.quit()
}
style : btnStyle;
z : 1;
}
//我們實現4個比較簡單的效果
Grid {
id : op;
anchors.left : parent.left;
anchors.leftMargin : 4;
anchors.bottom : parent.bottom;
anchors.bottomMargin : 4;
rows : 2;
columns : 2;
rowSpacing : 4;
columnSpacing : 4;
z : 1;
//柔化效果
Button {
text : "柔化";
style : btnStyle;
onClicked : {
//busy.running = true;
//processor.process(fileDialog.fileUrl, ImageProcessor.Soften);
}
}
//灰度效果
Button {
text : "灰度";
style : btnStyle;
onClicked : {
//busy.running = true;
//processor.process(fileDialog.fileUrl, ImageProcessor.Gray);
}
}
//浮雕效果
Button {
text : "浮雕";
style : btnStyle;
onClicked : {
//busy.running = true;
//processor.process(fileDialog.fileUrl, ImageProcessor.Emboss);
}
}
//黑白效果
Button {
text : "黑白";
style : btnStyle;
onClicked : {
//busy.running = true;
//processor.process(fileDialog.fileUrl, ImageProcessor.Binarize);
}
}
}
Rectangle {
anchors.left : parent.left;
anchors.top : parent.top;
anchors.bottom : openFile.bottom;
anchors.bottomMargin : - 6;
anchors.right : quit.right;
anchors.rightMargin : - 6;
color : "#404040";
opacity : 0. 7;
}
Rectangle {
anchors.left : parent.left;
anchors.top : op.top;
anchors.topMargin : - 4;
anchors.bottom : parent.bottom;
anchors.right : op.right;
anchors.rightMargin : - 4;
color : "#404040";
opacity : 0. 7;
}


