QT 大作业实现对图片与视频的处理

软件设计任务概述

        本次的实验在实验八的基础上进行整合,删除冗余的函数和操作按钮,修改不必要的跳转函数,优化处理,完成对视频、图像的操作。

本次的实验平台搭建用QT Create 和Opencv 一同完成。在对图片处理的过程中,只调用QT的库函数对图片的像素的Rgb进行处理,在对视频的处理上,调用Opencv 的库函数操作。在本次的实验分成两部分进行:一、对图片进行处理;二、完成对视频的处理。具体要求如下:

  1. 图像处理:对图像进行灰度化、二值化(阈值可调)、均值滤波、伽马变换(针对彩图)、边缘检测、高斯模糊、加水印、图片导出保存等功能。
  2. 视频处理:对每帧视频帧进行灰度化、二值化、边缘检测、缩放、局部马赛克等操作。

二、可行性研究、需求分析及分工 

2.1、可行性研究

        在实验八的基础上可知,Qt调用C/C++库函数可以完成对图像(QImage)的像素点的处理,所有在接下里的二值化等需求也是可行的,在查阅了相关的资料后得知,opencv可以对视频经行切片处理,获得帧,从而对视频经行转帧播放,同时在对帧即图像可以处理,所有视频的灰度化等是可行的。

2.2、需求分析

        对图片的处理是对像素点的处理,根据之前的方法知道,没有另外的需求。对视频的处理需要在QT中加入Opencv的库函数,调用 VideoCapture capture 来对视频进行分析和操作。

三、实现的过程与步骤

        3.1、基本界面的搭建

QT 大作业实现对图片与视频的处理_第1张图片

QT 大作业实现对图片与视频的处理_第2张图片

注意点在于:

1.对mainToolBar的引入是不可以直接的,因为在工具库中是没有这个工具的,所以在项目外打开 .ui 文件 在文件中加入下列代码实现对mainToolBar 的添加。


   
    Qt::ToolButtonIconOnly
   
   
    TopToolBarArea
   
   
    false
   
  

2.在之前实践的基础上,将减少不必要的操作,放入工具栏和两个Dock栏(左侧的是对图片的处理,右侧的是对视频的处理),在中间打破centralwidget布局,放入三个label,两个用来显示图片,在打开图片时隐藏一个(originMovieLabel),打开视频是,隐藏另外两个(originLabel、showLabel)。隐藏和显示的代码如下:

ui->originMovieLabel->setVisible(false);

 运行效果如下:

QT 大作业实现对图片与视频的处理_第3张图片

         3.2、警告窗口

        在本次的作用要求中,对提示警告窗进行了详细的制作,在其中加入图片和图标,和主窗口对应,相关代码和运行效果如下:

        QT 大作业实现对图片与视频的处理_第4张图片 

代码如下:

QMessageBox *msgBox=new QMessageBox();
msgBox->setWindowTitle(tr("关于本软件对话框"));
msgBox->setIconPixmap(QPixmap(":/img/img/warning.png"));
QIcon icon(":/img/img/need_icon.ico");
msgBox->setInformativeText(tr("没有图片"));
msgBox->setStyleSheet("QLabel{"
                "min-width: 200px;"
                "min-height: 100px; "
                "}");
msgBox->setWindowIcon(icon);
msgBox->show();

 3.3、图像处理

        在对图像处理中梳理其核心为对其与周边像素的处理,在此出对本软件的部分实现算法做一份介绍,如:灰度处理、均值滤波、二值化、边缘检测、伽马处理。

        3.3.1、读入文件

        调用QFileDialog读入文件,获得文件的地址信息,打开文件。如果打开失败,弹出提醒弹窗,读入成功,在originLabel中显示。

        3.3.2、灰度处理

        获得originLabel中的图片,对Qpixmap对象转变为QImage对象,获得图像的像素,获得其RGB的值,然后通过灰度公式对其进行计算,得出最后的RGB值,然后重新赋值给这个像素点,将像素点放回到图像从而得到最后的处理图像,显示在showlabel中。(这里用的是加权的计算方法)运行结果(图4-5)和代码如下:

QImage MainWindow::grayscale1(){
    QImage *origin =new QImage();
    、/*警告模块,参考上述3.2的代码内容*/
        *origin =ui->originLabel->pixmap()->toImage();
        QImage *newImage = new QImage(origin->width(), origin->height(), QImage::Format_ARGB32);
    for(int y = 0; yheight(); y++){
            //获取一行像素的首地址
            QRgb * line = (QRgb *)origin->scanLine(y);
            for(int x = 0; xwidth(); x++){
                //提取像素
                //灰度转换的一种方法(R G B 求平均值)
                int average = (qRed(line[x])*0.299 + qGreen(line[x])*0.587 + qBlue(line[x])*0.114);
                newImage->setPixel(x,y, qRgb(average, average, average));
            }
        }
    return *newImage;}

 

 

        3.3.3、二值化处理

        同上,获得图像的像素点,设置阈值,将图像灰度化处理,比较像素点灰度值与阈值的关系,大于设为黑色,即RGB(0,0,0);反正着设为RGB(255,255,255),组合显示。运行效果(图4-6)和代码如下:

QImage MainWindow::bianry1(QImage origin){
    /*警告模块,参考上述3.2的代码内容*/
     QImage *newImage=new QImage(origin.width(), origin.height(), QImage::Format_ARGB32);
    for(int y = 0; yheight(); y++){
            //获取一行像素的首地址
            QRgb * line = (QRgb *)origin.scanLine(y);
            for(int x = 0; xwidth(); x++){
                //提取像素
                int rgb_r=qRed(line[x]);
                if(rgb_r<=int(num)){
                   newImage->setPixel(x,y, qRgb(255,255,255));
                }else{
                   newImage->setPixel(x,y, qRgb(0,0,0));
                }
            }
        }
    return *newImage;}

QT 大作业实现对图片与视频的处理_第5张图片

 

3.3.4、均值滤波(阈值可调)

        同上,先获得像素点,然后根据所提供的阈值将所在的矩形(其为中心)的所有像素的RGB的值都相加,同时统计加入了几个像素点。计算出其平均值后再赋值,找下一个像素点重复上述的操作,以此达到对均值滤波的效果。此处的注意点在于对边界的判定和对像素点个数的判定。代码运行与截图(4-7)如下:(注意:此处代码有误,bug点应该在对便捷判断的地方,两层循环的里面的if ,自行改正啦,不然运行会出黑边

QImage MainWindow::average1(){
QImage *origin =new QImage();
    /*警告模块,参考上述4.2的代码内容*/
    *origin =ui->originLabel->pixmap()->toImage();
    QImage *newImage = new QImage(origin->width(), origin->height(), QImage::Format_ARGB32);
    qDebug()<height(); y++){
            //获取一行像素的首地址
            QRgb * line = (QRgb *)origin->scanLine(y);
            for(int x = 0; xwidth(); x++){
                //1.设法提去周边的数组
                int sum=0;double rgb_r=0;double rgb_b=0;double rgb_g=0;
                for(int y1=y-int(num/2);y1<(y+int(num/2));y1++){
                    for(int x1=x-int(num/2);x1<(x+int(num/2));x1++){
                        if(x1<0||y1<0||x1>x||y1>y) {break;}else{
                        rgb_r=rgb_r+qRed(line[x1]);
                        rgb_g=rgb_g+qGreen(line[x1]);
                        rgb_b=rgb_b+qBlue(line[x1]);
                        sum++;}
                    }
                }
                //2.计算平均值//3.放回数值          newImage->setPixel(x,y,qRgb(int(rgb_r/sum),int(rgb_g/sum),int(rgb_b/sum)));
            }
        }
    //4.打印照片
    return *newImage;}

 

3.3.5、边缘检测算法

本算法的实现采用canny算法,其先对图像进行灰度的处理,在进行高斯平滑算法处理,降低其噪点的存在,再计算梯度强度和方向,对图像非最大值进行抑制,双阀值检测与抑制孤立低阈值点,减少早点的存在,使图片的效果更加清晰,最后得出边缘检测的图。本处的代码较多,不做展示,详情看源码文件。运行截图如下:

QT 大作业实现对图片与视频的处理_第6张图片

 

相关整合代码如下:提供参照文档

QImage MainWindow::By1(QImage image){
    QImage *img =new QImage();
        *img=image;
    QImage img_gray=image;
   // QImage img_guass;

//**********高斯模糊开始
        int k=5;//高斯滤波器规模
        double kernel[10][10];
        generic_guess(kernel,k,1.4);
        QImage * t_img=new QImage(img_gray.width()+k-1,img_gray.height()+k-1,QImage::Format_ARGB32);
        QImage *img_guass=new QImage(img_gray.width(),img_gray.height(),QImage::Format_ARGB32);

        //lefttop
        for(int i=0;isetPixel(i,j,img_gray.pixel(0,0));
            }
        }
        //righttop
        for(int i=0;isetPixel(i,j,img_gray.pixel(img_gray.width()-1,0));
            }
        }
        //rightbottom
        for(int i=img_gray.width()+k/2;iwidth();++i){
            for(int j=0;jsetPixel(i,j,img_gray.pixel(img_gray.width()-1,img_gray.height()-1));
            }
        }
        //leftbottom
        for(int i=0;iheight();++j){
                t_img->setPixel(i,j,img_gray.pixel(0,img_gray.height()-1));
            }
        }
        //top
        for(int i=0;isetPixel(i+k/2,j,img_gray.pixel(i,0));
            }
        }
        //right
        for(int i=t_img->width()-k/2;iwidth();++i){
            for(int j=0;jsetPixel(i,j+k/2,img_gray.pixel(img_gray.width()-1,j));
            }
        }
        //bottom
        for(int i=0;iheight()-k/2;jheight();++j){
                t_img->setPixel(i+k/2,j,img_gray.pixel(i,img_gray.height()-1));
            }
        }
        //left
        for(int i=0;isetPixel(i,j+k/2,img_gray.pixel(0,j));
            }
        }
        for(int i=0;isetPixel(i+k/2,j+k/2,img_gray.pixel(i,j));
            }
        }

        for(int i=k/2;iwidth()-k/2;++i){
            for(int j=k/2;jheight()-k/2;++j){
                double temp=0;
                for(int ti=0;tipixel(i-k/2+ti,j-k/2+tj));
                    }
                }
                img_guass->setPixel(i-k/2,j-k/2,qRgb(temp,temp,temp));
            }
        }
//**************高斯模糊结束、end
//**************计算梯度强度和方向开始
        double** gradx=new double*[img->width()];
        for(int i=0;iwidth();++i)
            gradx[i]=new double[img->height()];
        double** grady=new double*[img->width()];
        for(int i=0;iwidth();++i)
            grady[i]=new double[img->height()];
        double** grad=new double*[img->width()];
        for(int i=0;iwidth();++i)
            grad[i]=new double[img->height()];
        double** dir=new double*[img->width()];
        for(int i=0;iwidth();++i)
            dir[i]=new double[img->height()];
        int k1=3;//sobel算子规模
        double kernelx[3][3]={-1,0,1,-2,0,2,-1,0,1};
        double kernely[3][3]={1,2,1,0,0,0,-1,-2,-1};

        QImage *t_img1=new QImage(img_gray.width()+k1-1,img_gray.height()+k1-1,QImage::Format_ARGB32);
        //lefttop
        for(int i=0;isetPixel(i,j,img_gray.pixel(0,0));
            }
        }
        //righttop
        for(int i=0;isetPixel(i,j,img_gray.pixel(img_gray.width()-1,0));
            }
        }
        //rightbottom
        for(int i=img_gray.width()+k1/2;iwidth();++i){
            for(int j=0;jsetPixel(i,j,img_gray.pixel(img_gray.width()-1,img_gray.height()-1));
            }
        }
        //leftbottom
        for(int i=0;iheight();++j){
                t_img1->setPixel(i,j,img_gray.pixel(0,img_gray.height()-1));
            }
        }
        //top
        for(int i=0;isetPixel(i+k1/2,j,img_gray.pixel(i,0));
            }
        }
        //right
        for(int i=t_img1->width()-k1/2;iwidth();++i){
            for(int j=0;jsetPixel(i,j+k1/2,img_gray.pixel(img_gray.width()-1,j));
            }
        }
        //bottom
        for(int i=0;iheight()-k1/2;jheight();++j){
                t_img1->setPixel(i+k1/2,j,img_gray.pixel(i,img_gray.height()-1));
            }
        }
        //left
        for(int i=0;isetPixel(i,j+k1/2,img_gray.pixel(0,j));
            }
        }
        for(int i=0;isetPixel(i+k1/2,j+k1/2,img_gray.pixel(i,j));
            }
        }
        for(int i=k1/2;iwidth()-k1/2;++i){
            for(int j=k1/2;jheight()-k1/2;++j){
                double tempx=0;
                double tempy=0;
                for(int ti=0;tipixel(i-k1/2+ti,j-k1/2+tj));
                        tempy+=kernely[ti][tj]*qRed(t_img1->pixel(i-k1/2+ti,j-k1/2+tj));
                    }
                }
                gradx[i-k1/2][j-k1/2]=tempx;//error
                grady[i-k1/2][j-k1/2]=tempy;
                grad[i-k1/2][j-k1/2]=sqrt(pow(tempx,2)+pow(tempy,2));
                double theta=atan(tempy/tempx)+90;
                if (theta >= 0 && theta < 45)
                    dir[i-k1/2][j-k1/2] = 2;
                else if (theta >= 45 && theta < 90)
                    dir[i-k1/2][j-k1/2] = 3;
                else if (theta >= 90 && theta < 135)
                    dir[i-k1/2][j-k1/2] = 0;
                else
                    dir[i-k1/2][j-k1/2] = 1;
            }
        }
        bool calcu=true;
//***********************计算梯度强度和方向结束
//***********************非极大值抑制开始

        if(!calcu){
            QMessageBox::critical(this,u8"提示",u8"未计算边缘强度和方向");

        }
        QColor c1(255,255,255);
        QColor c(0,0,0);
        QRgb edge = qRgb(c.red(),c.green(),c.blue());
        QRgb notedge = qRgb(c1.red(),c1.green(),c1.blue());

        QImage *img_nms=new QImage(img_guass->width(),img_guass->height(),QImage::Format_ARGB32);

        double temp=0;
        for(int i=0;iwidth();++i){
            for(int j=0;jheight();++j){
                temp+=grad[i][j];
            }
        }
        temp/=img_nms->width()*img_nms->height();
        double highthresh =temp;
        double lowthresh=highthresh;

        double N,NE,E,SW,W,SE,S,NW;
        double grad1=0,grad2=0,tantheta=0;
        for(int i=1;iwidth()-1;++i){
            for(int j=1;jheight();++j){
                N=grad[i][j-1];
                NE=grad[i+1][j-1];
                E=grad[i+1][j];
                SW=grad[i-1][j+1];
                W=grad[i-1][j];
                SE=grad[i+1][j+1];
                S=grad[i][j+1];
                NW=grad[i-1][j-1];
                if(dir[i][j]==0){
                    tantheta=abs(grady[i][j]/gradx[i][j]);
                    grad1=E*(1-tantheta)+NE*tantheta;
                    grad2=W*(1-tantheta)+SW*tantheta;
                }
                else if(dir[i][j]==1){
                    tantheta=abs(gradx[i][j]/grady[i][j]);
                    grad1=N*(1-tantheta)+NE*tantheta;
                    grad2=S*(1-tantheta)+SW*tantheta;
                }
                else if(dir[i][j]==2){
                    tantheta=abs(gradx[i][j]/grady[i][j]);
                    grad1=N*(1-tantheta)+NW*tantheta;
                    grad2=S*(1-tantheta)+SE*tantheta;
                }
                else if(dir[i][j]==3){
                    tantheta=abs(grady[i][j]/gradx[i][j]);
                    grad1=W*(1-tantheta)+NW*tantheta;
                    grad2=E*(1-tantheta)+SE*tantheta;
                }
                else{
                    grad1=highthresh;
                    grad2=highthresh;

                }


                if(grad[i][j]>grad1&&grad[i][j]>grad2){
                    img_nms->setPixel(i,j,edge);//black边缘
    //                gradcp[i][j]=highthresh;
                }
                else{
                    img_nms->setPixel(i,j,notedge);//white
                    grad[i][j]=0;
                }
            }
        }
//************非极大值抑制结束
//************双阈值检测开始
        QImage *img_dt=new QImage(img_nms->width(),img_nms->height(),QImage::Format_ARGB32);
            double** gradcp=new double*[img->width()];
            for(int i=0;iwidth();++i)
                gradcp[i]=new double[img->height()];


            for(int i=0;iwidth();++i){
                for(int j=0;jheight();++j){
                    if(grad[i][j]>highthresh){//强边缘
                        gradcp[i][j]=highthresh;
                        img_dt->setPixel(i,j,edge);
                    }
                    else if(grad[i][j]>lowthresh){//弱边缘
                        gradcp[i][j]=lowthresh;
                        img_dt->setPixel(i,j,edge);
                    }
                    else{//非边缘
                        gradcp[i][j]=0;
                        img_dt->setPixel(i,j,notedge);//抑制
                    }
                }
            }

//************双阈值检测结束
//************抑制孤立低阈值点开始
            QImage *img_st=new QImage(img_dt->width(),img_dt->height(),QImage::Format_ARGB32);
                int frac[8][2]={{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};
                for(int i=1;iwidth()-1;++i){
                    for(int j=1;jheight()-1;++j){
                        if(gradcp[i][j]==highthresh){//强边缘
                            img_st->setPixel(i,j,edge);
                        }
                        else if(gradcp[i][j]==lowthresh){//弱边缘
                            for(int p=0;p<8;++p){
                                if(gradcp[i+frac[p][0]][j+frac[p][1]]==highthresh){
                                    img_st->setPixel(i,j,edge);//边缘
                                    break;
                                }
                                img_st->setPixel(i,j,notedge);//非边缘
                            }
                        }
                        else//非边缘
                            img_st->setPixel(i,j,notedge);
                    }
                }
//*******最终结果如下
        return *img_st;/*}
    return *img;*/
}

如各位所见,代码量很大,而且...不是自己纯原创的

参考文档:边缘检测之Canny算法_Qt实现(C++)

3.3.6、伽马转变

        伽马转变是在图像处理中,将漂白或曝光过头或不足的照片经行修正,根据伽马变换的公式与其图像可知:gamma值小于1时,会拉伸图像中灰度级较低的区域,同时会压缩灰度级较高的部分;gamma值大于1时,会拉伸图像中灰度级较高的区域,同时会压缩灰度级较低的部分。获得图像的像素后,将其每一个RGB的值经行一次公式的运行后放回,得到相关的图片。运行截图与代码如下:

QImage MainWindow::gamma1(){
    QImage *image=new QImage();
    /*警告模块,参考上述3.2的代码内容*/
        *image=ui->originLabel->pixmap()->toImage();
        double d=num;
            QColor color;
            int height = image->height();
            int width = image->width();
            for (int i=0;ipixel(i,j));
                    double r = color.red();
                    double g = color.green();
                    double b = color.blue();
                    int R = qBound(0,(int)qPow(r,d),255);
                    int G = qBound(0,(int)qPow(g,d),255);
                    int B = qBound(0,(int)qPow(b,d),255);
                    image->setPixel(i,j,qRgb(R,G,B));
                }
            }
            return *image;}

 

4.3.7、保存图片

        获得showlabel中的图片信息,调用QPixmapsave()函数,使得可以保存图片,同时读取系统时间,将其作为命名的标题保存地址为程序编译的地址。相关代码如下:

void MainWindow::save(){
    QImage *image =new QImage();
    /*警告模块,参考上述3.2的代码内容*/
    *image = ui->showLabel->pixmap()->toImage();
    QPixmap p =QPixmap::fromImage(*image);
    //文件命名系统
    QTime current_time =QTime::currentTime();
    int hour = current_time.hour();//当前的小时
    int minute = current_time.minute();//当前的分
    int second = current_time.second();//当前的秒
    QString filename=QString::number(hour)+"_"+QString::number(minute)+"_"+QString::number(second)+"_"+QString::number(num)+".jpg";
    //保存图片
    p.save(filename,Q_NULLPTR,100);
    qDebug()<<"ok";}

3.4、视频处理

        在本处的视频处理中,引入opencv作为对视频的处理。将视频读入后,获得其每一帧的图像,然后处理

3.4.1、安装OpenCV

        在安装过程中注意其的报错,有可能就因为网络问题出现无法下载相关的库文件,在写函数的时候使无法发现的,但在运行的时候才会发现库文件的确实,最容易出错的为:opencv_ffmpeg_64.dllffmpeg_version.cmakeopencv_ffmpeg.dll

相关的参考资料如下:

        1.OpenCV安装教程  基于64位win10系统的QT+opencv环境配置_huadianyue的专栏-CSDN博客_opencv qt win10

        2.OpenCV Cmake-Configure报错的解决教程:

CMake opencv时Download: opencv_ffmpeg.dll、ippicv等失败的解决方法_楷尘·极客-CSDN博客_opencv_ffmpeg.dll下载

  1. 相关库文件国内映射口与ffmpeg_version.cmake下载问题

CMake编译OpenCV4.0时opencv_ffmpeg.dll等下载失败的解决思路总结 - 葫芦娃508 - 博客园

3.4.2、对.opr文件的操作

在安装完openCV后,需要在.opr文件中添加以下的信息(地址为你的配置地址):

INCLUDEPATH +=D:/qt/opencv-4.5.4/opencvlib/install/include
INCLUDEPATH +=D:/qt/opencv-4.5.4/opencvlib/install/include/opencv
INCLUDEPATH +=D:/qt/opencv-4.5.4/opencvlib/install/include/opencv2
LIBS +=D:/qt/opencv-4.5.4/opencvlib/install/x64/mingw/lib/libopencv_*.a

3.4.3、读取视频文件

在函数中调用QFileDialog读入文件,获得文件的地址信息,打开视频文件,调用capture.open(video_path.toStdString());打开视频。用capture.isOpened()判断文件是否正确打开。没有提供相关的警告弹窗。打开视频就让前面显示图片的label暂时消失,并且显示originMovieLabel。计算帧率和视频时间。值得注意的是:在本段代码里需要注意的是,opencv用的是String类型的字符串,但QT用的是QString类型的字符串,其不是一样的,需要进行处理和转置,其中可能出现乱码的可能性。相关代码与截图(图4-10)如下:

void MainWindow::openMovie(){
    QString video_path = QFileDialog::getOpenFileName(this,tr("选择视频"),"E:/Qt/qtworks/MainWindow/images",tr("Video (*.WMV *.mp4 *.rmvb *.flv)"));
        if(video_path!=nullptr){
        //打开视频文件:其实就是建立一个VideoCapture结构
            capture.open(video_path.toStdString());
            //检测是否正常打开:成功打开时,isOpened返回ture
            if (!capture.isOpened()){
                /*警告模块,参考上述3.2的代码内容*/
            //对label的管理
            ui->showLabel->setVisible (false);//让他暂时消失
            ui->originLabel->setVisible (false);//让他暂时消失
            ui->originMovieLabel->setVisible(true);//视频部分显示出来
            //获取整个帧数
            long totalFrameNumber = capture.get(CAP_PROP_FRAME_COUNT);
            //设置开始帧()
            long frameToStart = 0;
            capture.set(CAP_PROP_POS_FRAMES, frameToStart);
            //获取帧率
            double rate = capture.get(CAP_PROP_FPS);
            delay = 1000 / rate;
            timer.start(delay);
            type=0;
            //timer.start();
            isstart=!isstart;
            isMovie=1;
            isPhoto=0;
            isPhoto_r=0;
        }
}

 

4.4.4、视频播放与视频处理

其原理是调用MAT对象的函数,获得视频的帧,对帧进行操作,然后返回继续显示,在不断的重复中输出处理后的视频图像。本次实验实验对视频的二值化处理、灰度处理、边缘检测处理、马赛克、缩放的处理。

  1. 二值化

        调用了opencv的自带函数threshold(frameframe,too255THRESH_BINARY);将Mat对象处理返回,然后转化图像显示。相关运行截图(图4-11)如下。

  1. 灰度处理

对视频的灰度处理也是调用系统函数cvtColor(frame,frame,CV_BGR2GRAY);,不然其无法平滑播放。相关运行截图如下。

  1. 视频边缘检测处理

边缘检测调用前面对图像的处理,使其完成边缘检测,但因为要循环的数据过大,使其无法平稳的播放。相关运行截图如下。

  1. 视频马赛克处理(阈值可调)

与上述的均值有些相似,划定一个大小的矩阵,遍历矩阵中的所有像素,将矩阵最开始的像素的值赋值给所有的点,然后输入。相关截图如下。

QT 大作业实现对图片与视频的处理_第7张图片

QT 大作业实现对图片与视频的处理_第8张图片 

QT 大作业实现对图片与视频的处理_第9张图片 

 QT 大作业实现对图片与视频的处理_第10张图片

 马赛克的相关代码

Mat MainWindow::masaike(Mat src){
    int width = src.rows;	//图片的长度
    int height = src.cols;	//图片的宽度
    if(scale==NULL){scale=10;}
    int arr = scale;//试图调节
    //i和j代表了矩形区域的左上角的像素坐标
    for (int i = 0; i < width; i+=arr) {//int i = width/2.5; i < width/1.5; i+=arr
        for (int j = 0; j < height; j+=arr) {//int j = height/2.5; j < height/1.5; j+=arr
        //对矩形区域内的每一个像素值进行遍历
            for (int k = i; k < arr + i && k < width; k++) {
                for (int m = j; m < arr + j && m < height; m++) {
                    //在这里进行颜色的修改
                    //at(k, m)[0]=qRed();取出像素点中的rgb三数值,不过这里是对数组的形式
                    src.at(k, m)[0] = src.at(i, j)[0];//B
                    src.at(k, m)[1] = src.at(i, j)[1];//G
                    src.at(k, m)[2] = src.at(i, j)[2];//R
                }
            }
        }
    }
    return src;
}

最后放上参考文档:使用QT5+Opencv完成简单的图像处理及视频处理软件_每天进步一点点!-CSDN博客_opencv图像处理软件

你可能感兴趣的:(qt,qt,音视频,opencv)