基于qml创建最简单的图像处理程序(2)-使用c++&qml进行图像处理

《基于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

qml实现了不错的界面,但是图像处理这块不是它强项,它能够提供的就是qimage这样的图像,对像素的处理就是对图像的处理,而最简单、最直接的方法就是使用c++的代码进行像素处理。

这里就涉及到c++&qml联合程序设计的具体内容了。这方面涉及到的东西有点多,首先我们需要解决的是qml和c++的联合问题。当然我们在搭建这个框架的时候,可能会有比较多一些的问题—另一个方面,当框架搭建好了以后,使用起来会比较方便。

一、编写按钮触发事件

现有的例子,已经实现了qml的界面,并且能够打开、显示一个新的图像;我们甚至为后面的图像处理预留了几个按钮的位置,下面我们首先就是要触发这些按钮的事件。

//灰度效果d
        Button {
            text: "灰度";
            style: btnStyle;
            onPressedChanged: {
                busy.running = true;
              //  processor.process(fileDialog.fileUrl, ImageProcessor.Gray);
            }
        }
        //浮雕效果
        Button {
            text: "浮雕";
            style: btnStyle;
            onPressedChanged: {
                busy.running = true;
              //  processor.process(fileDialog.fileUrl, ImageProcessor.Emboss);
            }
        }
        //黑白效果
        Button {
            text: "黑白";
            style: btnStyle;
            onPressedChanged: {
                busy.running = true;
              //  processor.process(fileDialog.fileUrl, ImageProcessor.Binarize);
            }
        }

这个地方有一个小细节,那就是

onPressedChanged()

onClick()

的区别。这两者表示的都是“按下”这个事件,他们的不同在于onClick()要多了一个“按下后抬起”的动作。所以一般来说,对于桌面运用,click用的多一点,而对于Android,onPressedChanged多一点。

二、触发图像处理算法

我们可以看到上面代码中,每一种处理后面,都有一行注释,调用的是processor对象的一个函数,那么这个函数是从哪里来的了?它的定义来自这里

//需要特别注意,这个组件来自imageprocessor这个类,通过这种方法进行集成
    ImageProcessor {
        id: processor;
        onFinished: {
            imageViewer.source = "file:///" +newFile;
        }
    }

它的意思是processor对象是ImageProcessor类的一个实例,那么ImageProcessor又是从哪里来的了?

它的定义来自于

//将c++中定义的类给接过来,在这个定义中,ImageProcessor是c++中函数名,GO.ImageProcessor是你在qml中使用的名称
qmlRegisterType<ImageProcessor>("GO.ImageProcessor", 1, 0,"ImageProcessor");

其中qmlRegisterType是类的引入,类似dllimport之类,而

<ImageProcessor>

"ImageProcessor"

一般来说,都是来自于你的c++的函数名称;而

"GO.ImageProcessor"

是你在qml中的头文件.

此外,1,0是你的版本号。

所以这个地方有两个头文件,在main.cpp中,引入

#include "imageProcessor.h"

而在qml中,这样引入

import GO.ImageProcessor 1.0

那么我们在这里主要讨论的就是如何从c++中将行数引接过来的。

、C++中具体算法实现

那我们就来看c++类中的ImageProcessor 是如何实现的,它的代码地址来自:

它的原型为:

void process(QString sourceFile, ImageProcessor::ImageAlgorithm algorithm)
{
QFileInfo fi(sourceFile);
QString destFile = QString("%1/%2_%3").arg(m_tempPath).arg((int)algorithm).arg(fi.fileName());
AlgorithmRunnable *r = new AlgorithmRunnable(sourceFile,destFile,algorithm,this);
m_runnables.append(r);
r->setAutoDelete(false);
QThreadPool::globalInstance()->start(r);
}

它设定了一系列参数,主要是创建了AlgorithmRunnalbe,然后通过QThreadPool打开新线程运行算法。那么主要的函数体在AlgorithmRunnable中的。由于涉及到较多的具体内容,这里不展开说明,大家可以参考全部代码。

我们关注的是图像处理函数,在这个项目中实现了以下内容:

//具体的图像处理算法,注意图片处理的结果直接保存到了destFile中去//
static void _gray(QString sourceFile, QString destFile)
{
    QImage image(sourceFile);
    if(image.isNull())
    {
        qDebug() << "load " << sourceFile << " failed! ";
        return;
    }
    qDebug() << "depth - " << image.depth();

int width = image.width();
    int height = image.height();
    QRgb color;
    int gray;
    for(int i = 0; i < width; i++)
    {
        for(int j= 0; j < height; j++)
        {
            color = image.pixel(i, j);
            gray = qGray(color);
            image.setPixel(i, j, qRgba(gray, gray, gray, qAlpha(color)));
        }
    }

image.save(destFile);
}

static void _binarize(QString sourceFile, QString destFile)
{
    QImage image(sourceFile);
    if(image.isNull())
    {
        qDebug() << "load " << sourceFile << " failed! ";
        return;
    }
    int width = image.width();
    int height = image.height();
    QRgb color;
    QRgb avg;
    QRgb black = qRgb(0, 0, 0);
    QRgb white = qRgb(255, 255, 255);
    for(int i = 0; i < width; i++)
    {
        for(int j= 0; j < height; j++)
        {
            color = image.pixel(i, j);
            avg = (qRed(color) + qGreen(color) + qBlue(color))/3;
            image.setPixel(i, j, avg >= 128 ? white : black);
        }
    }
    image.save(destFile);
}

static void _emboss(QString sourceFile, QString destFile)
{
    QImage image(sourceFile);
    if(image.isNull())
    {
        qDebug() << "load " << sourceFile << " failed! ";
        return;
    }
    int width = image.width();
    int height = image.height();
    QRgb color;
    QRgb preColor = 0;
    QRgb newColor;
    int gray, r, g, b, a;
    for(int i = 0; i < width; i++)
    {
        for(int j= 0; j < height; j++)
        {
            color = image.pixel(i, j);
            r = qRed(color) - qRed(preColor) + 128;
            g = qGreen(color) - qGreen(preColor) + 128;
            b = qBlue(color) - qBlue(preColor) + 128;
            a = qAlpha(color);
            gray = qGray(r, g, b);
            newColor = qRgba(gray, gray, gray, a);
            image.setPixel(i, j, newColor);
            preColor = newColor;
        }
    }
    image.save(destFile);
}
//END 具体的图像处理算法,注意图片处理的结果直接保存到了destFile中去//

甚至不用去看算法的实现(因为最后我们肯定是要使用OpenCV来做图像处理的),这3个图像处理的函数都是非常统一的

static void _binarize(QString sourceFile, QString destFile)

比如返回类型为void,第一个参数为输入图像,第二个参数为输出图片。从这里也可以看出,在我们这个项目中,是通过地址(而不是内存)来传递数据的。如果我们想要添加新的算法,修改现有算法,直接修改这几个函数、添加相关界面就可以。

而下一步,最关键的一步,也是原书例子没有实现的,就是添加OpenCV的代码,使用它来替代进行图像处理。

来自为知笔记(Wiz)

附件列表

原文地址:https://www.cnblogs.com/jsxyhelu/p/8361441.html

时间: 2024-10-04 12:45:40

基于qml创建最简单的图像处理程序(2)-使用c++&qml进行图像处理的相关文章

基于qml创建最简单的图像处理程序(1)-基于qml创建界面

为什么使用QT,包括进一步使用QML?两个主要原因,一是因为我是一个c++程序员,有语言使用惯性:二是我主要做图像处理方面工作,使用什么平台对于我来说不重要,我只需要在不同平台上面能够运行我的图像处理程序(而主要是和OpenCV有关系的).所以选择QT,它能够在win/linux/android,包括PI上面都提供不错的GUI支持:而如果我想在Android上编写图像处理程序,又主要遇到两个问题,一是相机的获取.OpenCV的videocapture在Android上支持不好,在最新版本的Ope

使用python2与python3创建一个简单的http服务(基于SimpleHTTPServer)

python2与python3基于SimpleHTTPServer创建一个http服务的方法是不同的: 一.在linux服务器上面检查一下自己的python版本:如: [[email protected] ~]# python -V Python 2.7.5 如果是在2.7的环境下创建,则使用如下命令: [[email protected] ~]# python -m SimpleHTTPServer 8880 Serving HTTP on 0.0.0.0 port 8880 ... 后面88

图像处理程序框架—MFC相关知识点

CDC:Windows使用与设备无关的图形设备环境(DC :Device Context) 进行显示 . MFC基础类库定义了设备环境对象类----CDC类.CDC与CGdiObject的关系 说道CDC类就不能不提一下GdiObject---图形对象类. 在Windows应用程序中,设备环境与图形对象共同工作,协同完成绘图显示工作.就像画家绘画一样,设备环境好比是画家的画布,图形对象好比是画家的画笔.用画笔在画布上绘画,不同的画笔将画出不同的画来.选择合适的图形对象和绘图对象,才能按照要求完成

基于QProbe创建基本Android图像处理框架

先来看一个GIF 这个GIF中有以下几个值得注意的地方 这个界面是基本的主要界面所应该在的地方.其右下角有一个"+"号,点击后,打开图像采集界面 在这个界面最上面的地方,显示的是当前图像处理的状态.(一般来说,是成功/不成功,或者是存在什么问题). 固然采用文章显示状态的方法比较简陋,但是也是能够达到提示用户正确拍摄的目的的:另一个方面,如果能够正确显示文字,那么修改成显示动画也是有方法的. 当识别图片发生变化的时候,显示的状态也随之改变. 当识别出正确的结果,跳转到图像处理界面. 那

基于Socket创建Web服务

基于Socket创建Web服务 为什么要使用Socket呢,我们来看下图 Socket原理图回顾: -------------------编写SocketService,完成字母小写转大写功能----------------------------- ServerSocket服务器端代码如下: public static void main(String[] args) throws IOException { // 1:建立服务器端的tcp socket服务,必须监听一个端口 ServerSo

基于BP神经网络的简单字符识别算法自小结(C语言版)

本文均属自己阅读源码的点滴总结,转账请注明出处谢谢. 欢迎和大家交流.qq:1037701636 email:[email protected] 写在前面的闲话: 自我感觉自己应该不是一个很擅长学习算法的人,过去的一个月时间里因为需要去接触了BP神经网络.在此之前一直都认为算法界的神经网络.蚁群算法.鲁棒控制什么的都是特别高大上的东西,自己也就听听好了,未曾去触碰与了解过.这次和BP神经网络的邂逅,让我初步掌握到,理解透彻算法的基本原理与公式,转为计算机所能识别的代码流,这应该就是所谓的数学和计

基于Struts1框架的简单工程搭建

新进入了某坑爹外包公司,所有的项目几乎都是用很古老的框架struts1,这里对struts温习下,并搭建了一个简单的登录工程. 1.Eclipse下创建一个Web工程,工程名称StrutsOneDemo,根目录修改为WebRoot(这样的Web工程可以在myeclipse下正常运行),该工程实现登录功能: 2.在lib中添加Struts1所需的jar包,这里使用的是1.3.10版本的jar包: 3.在src下创建三个包com.by.action.com.by.form.com.by.manage

创建一个简单的 MDM 服务器(1)

前提:已获得 APNS 证书 ,已完成 MDM 配置描述文件的制作.请参考< MDM 证书申请流程 >一文和<配置MDM Provisioning Profile>. 环境:OSX 10.9.2,JDK 1.6,Eclipse JavaEE Helois,Tomcat 7.0 一.前言 <THE IOS MDMPROTOCOL>(即Inside Apple MDM)一文中描述了一个简单 MDM Server Python 实现(server.py).笔者也曾参照此文配置

django创建一个简单的web站点

一.新建project 使用Pycharm,File->New Project-,选择Django,给project命名 (project不能用test命名) 新建的project目录如下: settings.py:工程相关的配置 urls.py:网站访问入口,对应到views wigs.py:部署相关 manage.py:执行命令 templates:html等静态文件 备注:新建工程后需要安装django的lib包,然后验证django是否安装成功 >>> import dja