zoukankan      html  css  js  c++  java
  • core组件进阶

    访问图像像素

    存储方式

    BGR连续存储有助于提升图像扫描速度。

    isContinuous()判断是否是连续存储。

    颜色空间缩减

    仅用这些颜色中具有代表性的很小的部分,就足以达到同样的效果。

    将现有颜色空间值除以某个输入值,获得较少的颜色数。

    LUT函数:look up table操作

    用于批量进行图像元素查找、扫描和操作图像。

     使用方法如下:

    1 Mat lookUpTable(1,256,CV_8U);
    2 uchar* p = lookUpTable.data;
    3 for(int i=0;i<256;i++)
    4     p[i] = table[i];
    5 //然后调用函数(I是输入,J是输出)
    6 for(int i=0;i<times;++i)
    7     LUT(I,lookUpTable,J);

    计时函数

    两个函数组合起来使用:

    double time0 = static_cast<double>(getTickCount());//记录起始时间
    //进行图像处理。。。。。。
    time0 = ((double)getTickCount() - time0 ) / getTickFrequency();
    cout << "此方法运行时间" << time0 << "" << endl;//输出运行时间

    访问图像中像素的三类方法

    要求:减少图像中颜色的数量,比如原来的图像是256种颜色,希望它变成64种颜色,只需将原来颜色除以4(整除)以后再乘以4就可以

    • 方法一,指针访问:C操作符[];
    • 方法二,迭代器iterator
    • 方法三,动态地址计算

    方法一

     1 //---------------------------------【头文件、命名空间包含部分】--------------------------
     2 //        描述:包含程序所使用的头文件和命名空间
     3 //-----------------------------------------------------------------------------------------------
     4 #include <opencv2/core/core.hpp>  
     5 #include <opencv2/highgui/highgui.hpp>  
     6 #include <iostream>  
     7 using namespace std;  
     8 using namespace cv;  
     9 
    10 //-----------------------------------【全局函数声明部分】-----------------------------------
    11 //          描述:全局函数声明
    12 //-----------------------------------------------------------------------------------------------
    13 void colorReduce(Mat& inputImage, Mat& outputImage, int div);  
    14 
    15 //--------------------------------------【main( )函数】---------------------------------------
    16 //          描述:控制台应用程序的入口函数,我们的程序从这里开始执行
    17 //-----------------------------------------------------------------------------------------------
    18 int main( )  
    19 {  
    20     //【1】创建原始图并显示
    21     Mat srcImage = imread("1.jpg");  
    22     imshow("原始图像",srcImage);  
    23 
    24     //【2】按原始图的参数规格来创建创建效果图
    25     Mat dstImage;
    26     dstImage.create(srcImage.rows,srcImage.cols,srcImage.type());//效果图的大小、类型与原图片相同 
    27 
    28     //【3】记录起始时间
    29     double time0 = static_cast<double>(getTickCount());  
    30     printf("
    
    			   当前使用的OpenCV版本为:" CV_VERSION );
    31 
    32     //【4】调用颜色空间缩减函数
    33     colorReduce(srcImage,dstImage,32);  
    34 
    35     //【5】计算运行时间并输出
    36     time0 = ((double)getTickCount() - time0)/getTickFrequency();
    37     cout<<"	此方法运行时间为: "<<time0<<""<<endl;  //输出运行时间
    38 
    39     //【6】显示效果图
    40     imshow("效果图",dstImage);  
    41     waitKey(0);  
    42 }  
    43 
    44 
    45 //---------------------------------【colorReduce( )函数】---------------------------------
    46 //          描述:使用【指针访问:C操作符[ ]】方法版的颜色空间缩减函数
    47 //----------------------------------------------------------------------------------------------
    48 void colorReduce(Mat& inputImage, Mat& outputImage, int div)  //div是要转成多少种颜色的数量
    49 {  
    50     //参数准备
    51     outputImage = inputImage.clone();  //拷贝实参到临时变量
    52     int rowNumber = outputImage.rows;  //行数
    53     int colNumber = outputImage.cols * outputImage.channels();  //列数 x 通道数=每一行元素的个数
    54 
    55     //双重循环,遍历所有的像素值
    56     for(int i = 0;i < rowNumber;i++)  //行循环
    57     {  
    58         uchar* data = outputImage.ptr<uchar>(i);  //获取第i行的首地址
    59         for(int j = 0;j < colNumber;j++)   //列循环
    60         {      
    61             // ---------【开始处理每个像素】-------------     
    62             data[j] = data[j]/div*div + div/2; 
    63             //可以等效使用指针运算从一列移动到下一列,所以还可以这样写:
    64             // *data++ = *data/div*div + div/2;
    65             // ----------【处理结束】---------------------
    66         }  //行处理结束
    67     }  
    68 }  

    Mat类有若干成员函数可以获取图像的属性。公有成员变量cols和rows给出了图像的宽和高,成员函数channels()用于返回图像的通道数。

    ptr函数可以得到图像任意行的首地址,ptr是模板函数,返回第i行的首地址。

    方法二:

    获得图像矩阵的begin和end,然后增加迭代从begin到end,将*操作符添加在迭代指针前,即可访问当前指向的内容。

    相比用指针直接访问可能出现越界问题,迭代器很安全。

     1 //-------------------------------------【colorReduce( )函数】-----------------------------
     2 //        描述:使用【迭代器】方法版的颜色空间缩减函数
     3 //----------------------------------------------------------------------------------------------
     4 void colorReduce(Mat& inputImage, Mat& outputImage, int div)  
     5 {  
     6     //参数准备
     7     outputImage = inputImage.clone();  //拷贝实参到临时变量
     8     //获取迭代器
     9     Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>();  //初始位置的迭代器
    10     Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>();  //终止位置的迭代器
    11 
    12     //存取彩色图像像素
    13     for(;it != itend;++it)  
    14     {  
    15         // ------------------------【开始处理每个像素】--------------------
    16         (*it)[0] = (*it)[0]/div*div + div/2;  
    17         (*it)[1] = (*it)[1]/div*div + div/2;  
    18         (*it)[2] = (*it)[2]/div*div + div/2;  //三个通道
    19         // ------------------------【处理结束】----------------------------
    20     }  
    21 }  

    方法三:

     1 //----------------------------------【colorReduce( )函数】-------------------------------
     2 //          描述:使用【动态地址运算配合at】方法版本的颜色空间缩减函数
     3 //----------------------------------------------------------------------------------------------
     4 void colorReduce(Mat& inputImage, Mat& outputImage, int div)  
     5 {  
     6     //参数准备
     7     outputImage = inputImage.clone();  //拷贝实参到临时变量
     8     int rowNumber = outputImage.rows;  //行数
     9     int colNumber = outputImage.cols;  //列数
    10 
    11     //存取彩色图像像素
    12     for(int i = 0;i < rowNumber;i++)  
    13     {  
    14         for(int j = 0;j < colNumber;j++)  
    15         {      
    16             // ------------------------【开始处理每个像素】--------------------
    17             outputImage.at<Vec3b>(i,j)[0] =  outputImage.at<Vec3b>(i,j)[0]/div*div + div/2;  //蓝色通道
    18             outputImage.at<Vec3b>(i,j)[1] =  outputImage.at<Vec3b>(i,j)[1]/div*div + div/2;  //绿色通道
    19             outputImage.at<Vec3b>(i,j)[2] =  outputImage.at<Vec3b>(i,j)[2]/div*div + div/2;  //红是通道
    20             // -------------------------【处理结束】----------------------------
    21         }  // 行处理结束     
    22     }  
    23 }  

    Mat类的成员函数at(int x,int y)可以用来存取图像元素。要确保指定的数据类型要和矩阵中的数据类型相符合,因为at方法本身不会对任何数据类型进行转换。

    对于一个包含彩色图像的Mat,会返回一个有三个8位数组成的向量。opencv将此类型的向量定义为Vec3b,即有三个unsigned char组成的向量,这也解释了为什么存取彩色图像像素的代码的形式:

    1 image.at<Vec3b>(j,i)[channel]=value;

    感兴趣区域:ROI

    这个区域是图像分析所关注的重点,圈住这个区域,方便进行进一步的处理。使用ROI指定想读入的目标,可以减少处理时间,提升精度,带来很大便利。

    定义ROI区域的方法有两种:

    第一种是使用表示矩形区域的Rect。指定矩形的左上角坐标和矩形的weidth和heigth

    1 Mat imageROI;
    2 imageROI = image(Rect(500,250,logo.cols,logo.rows))

    第二种指定ROI的行或列的范围Range。Range是指起始索引到终止索引(不包括终止索引)的一段连续序列:

    1 imageROI = image(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));

    下面代码中,通过一个图像掩模,直接将插入处的像素设置为logo图像的像素值,这样效果会很逼真。

     1 //-----ROI_AddImage()函数
     2 //利用感兴趣区域ROI实现图像叠加
     3 bool ROI_AddImage()
     4 {
     5     //1、读入图像
     6     Mat srcImagel = imread("doata");
     7     Mat logoImage = imread("dota_logo.jpg");
     8     if(!srcImagel.data)
     9     {
    10         printf("读取错误!
    ");
    11         return false;
    12     }
    13     if(!logoImage.data)
    14     {
    15         printf("读取错误!
    ");
    16         return false;
    17     }
    18     
    19     //2、定义一个Mat类型并给其设定ROI区域
    20     Mat imageROI = srcImagel(Rect(200,250,logoImage.cols,logoImage.rows));
    21     //3、加载掩模(必须是灰度图)
    22     Mat mask = imread("dota_logo.jpg",0);
    23     //4、将掩模复制到ROI
    24     logoImage.copyTo(imageROI,mask);
    25     //5、显示结果
    26     namedWindow("test");
    27     imshow("test",srcImagel);
    28     return true;
    29 }

    图像掩模一般用来对处理的图像(全部或者局部)进行遮挡,来控制图像处理的区域或处理过程。

    掩模一般是小于等于源图像的单通道矩阵,掩模中的值分为两种0和非0。以Mat::copyTo为例,当mask的值不为0,则将源图像拷贝到目标图像,当mask为0,则不进行拷贝,目标图像保持不变。

    线性混合操作

    线性混合操作是一种典型的二元(两个输入)的像素操作,它的理论公式如下:

    通过范围0~1之间改变alpha值,来对两幅图像f(x)或两段视频产生时间上的画面叠化效果,就想幻灯片放映和电影制作中的那样,也就是在幻灯片翻页时设置的前后叶缓慢过度叠加效果。

    主要用到了addWeighted函数。

    计算数组加权和:addWeighted函数

    这个函数的作用是计算两个数组(图像阵列)的加权和:

    void addWeighted(inputarray src1, double alpha, inputarray arc2, double beta, double gamma, outputarray dst, int dtyoe=-1);

    (1)需要加权的第一个数组,常常填一个Mat

    (2)alpht,第一个数组的权重

    (3)src2,第二个数组,和第一个数组拥有相同的尺寸和通道数

    (4)beta,第二个数组的权重值

    (5)gamma,一个加到权重总和上的标量值

    (6)dst,输出的数组,和输入的两个数组有相同的尺寸和通道数

    (7)dtype,输出阵列的可选深度,默认-1,。当两个输入数组具有相同的深度时,这个参数设置为-1。

    最终的计算结果:

    其中I是多维数组的索引值。每个通道都要独立的进行处理。当输出数组的深度为CV_32S时,这个函数就不适用了。

     1 /---------------------------------【LinearBlending()函数】-------------------------------------
     2 // 函数名:LinearBlending()
     3 // 描述:利用cv::addWeighted()函数实现图像线性混合
     4 //--------------------------------------------------------------------------------------------
     5 bool  LinearBlending()
     6 {
     7     //【0】定义一些局部变量
     8     double alphaValue = 0.5; 
     9     double betaValue;
    10     Mat srcImage2, srcImage3, dstImage;
    11 
    12     // 【1】读取图像 ( 两幅图片需为同样的类型和尺寸 )
    13     srcImage2 = imread("mogu.jpg");
    14     srcImage3 = imread("rain.jpg");
    15 
    16     if( !srcImage2.data ) { printf("读取srcImage2错误! 
    "); return false; }
    17     if( !srcImage3.data ) { printf("读取srcImage3错误! 
    "); return false; }
    18 
    19     // 【2】进行图像混合加权操作
    20     betaValue = ( 1.0 - alphaValue );
    21     addWeighted( srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);
    22 
    23     // 【3】显示原图窗口
    24     imshow( "<2>线性混合示例窗口【原图】", srcImage2 );
    25     imshow( "<3>线性混合示例窗口【效果图】", dstImage );
    26 
    27     return true;
    28 
    29 }

    初级图像混合

      1 //---------------------------------【头文件、命名空间包含部分】-------------------------------
      2 //        描述:包含程序所使用的头文件和命名空间
      3 //------------------------------------------------------------------------------------------------                                                                                 
      4 #include <opencv2/core/core.hpp>
      5 #include <opencv2/highgui/highgui.hpp>
      6 #include <iostream>
      7 
      8 using namespace cv;
      9 using namespace std;
     10 
     11 
     12 //-----------------------------------【全局函数声明部分】--------------------------------------
     13 //    描述:全局函数声明
     14 //-----------------------------------------------------------------------------------------------
     15 bool  ROI_AddImage();
     16 bool  LinearBlending();
     17 bool  ROI_LinearBlending();
     18 void   ShowHelpText();
     19 
     20 //-----------------------------------【main( )函数】--------------------------------------------
     21 //    描述:控制台应用程序的入口函数,我们的程序从这里开始
     22 //-----------------------------------------------------------------------------------------------
     23 int main(   )
     24 {
     25     //system调用dos命令
     26     //color 6f是用来设置dos窗口颜色的;1设置窗口背景颜色,f设置窗口字体颜色。
     27     system("color 6F");
     28  
     29     ShowHelpText();
     30 
     31     if(ROI_AddImage( ) && LinearBlending( ) && ROI_LinearBlending( ))
     32     {
     33         cout<<endl<<"
    运行成功,得出了需要的图像";
     34     }
     35 
     36     waitKey(0);//等待键位操作,按下-> 返回键盘的操作值,否则返回-1
     37     return 0;
     38 }
     39 
     40 
     41 //-----------------------------------【ShowHelpText( )函数】----------------------------------
     42 //         描述:输出一些帮助信息
     43 //----------------------------------------------------------------------------------------------
     44 void ShowHelpText()
     45 {
     46     //输出欢迎信息和OpenCV版本
     47     printf("
    
    			非常感谢购买《OpenCV3编程入门》一书!
    ");
     48     printf("
    
    			此为本书OpenCV3版的第25个配套示例程序
    ");
     49     printf("
    
    			   当前使用的OpenCV版本为:" CV_VERSION );
     50     printf("
    
      ----------------------------------------------------------------------------
    ");
     51 }
     52 
     53 
     54 
     55 
     56 //----------------------------------【ROI_AddImage( )函数】----------------------------------
     57 // 函数名:ROI_AddImage()
     58 //    描述:利用感兴趣区域ROI实现图像叠加
     59 //----------------------------------------------------------------------------------------------
     60 bool  ROI_AddImage()
     61 {
     62 
     63     // 【1】读入图像
     64     Mat srcImage1= imread("dota_pa.jpg");
     65     Mat logoImage= imread("dota_logo.jpg");
     66     if( !srcImage1.data ) { printf("读取srcImage1错误~! 
    "); return false; }
     67     if( !logoImage.data ) { printf("读取logoImage错误~! 
    "); return false; }
     68 
     69     // 【2】定义一个Mat类型并给其设定ROI区域
     70     Mat imageROI= srcImage1(Rect(200,250,logoImage.cols,logoImage.rows));
     71 
     72     // 【3】加载掩模(必须是灰度图)
     73     Mat mask= imread("dota_logo.jpg",0);
     74 
     75     //【4】将掩膜拷贝到ROI
     76     logoImage.copyTo(imageROI,mask);
     77 
     78     // 【5】显示结果
     79     namedWindow("<1>利用ROI实现图像叠加示例窗口");
     80     imshow("<1>利用ROI实现图像叠加示例窗口",srcImage1);
     81 
     82     return true;
     83 }
     84 
     85 
     86 //---------------------------------【LinearBlending()函数】-------------------------------------
     87 // 函数名:LinearBlending()
     88 // 描述:利用cv::addWeighted()函数实现图像线性混合
     89 //--------------------------------------------------------------------------------------------
     90 bool  LinearBlending()
     91 {
     92     //【0】定义一些局部变量
     93     double alphaValue = 0.5; 
     94     double betaValue;
     95     Mat srcImage2, srcImage3, dstImage;
     96 
     97     // 【1】读取图像 ( 两幅图片需为同样的类型和尺寸 )
     98     srcImage2 = imread("mogu.jpg");
     99     srcImage3 = imread("rain.jpg");
    100 
    101     if( !srcImage2.data ) { printf("读取srcImage2错误! 
    "); return false; }
    102     if( !srcImage3.data ) { printf("读取srcImage3错误! 
    "); return false; }
    103 
    104     // 【2】进行图像混合加权操作
    105     betaValue = ( 1.0 - alphaValue );
    106     addWeighted( srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);
    107 
    108     // 【3】显示原图窗口
    109     imshow( "<2>线性混合示例窗口【原图】", srcImage2 );
    110     imshow( "<3>线性混合示例窗口【效果图】", dstImage );
    111 
    112     return true;
    113 
    114 }
    115 
    116 //---------------------------------【ROI_LinearBlending()】-------------------------------------
    117 // 函数名:ROI_LinearBlending()
    118 // 描述:线性混合实现函数,指定区域线性图像混合.利用cv::addWeighted()函数结合定义
    119 //              感兴趣区域ROI,实现自定义区域的线性混合
    120 //--------------------------------------------------------------------------------------------
    121 bool  ROI_LinearBlending()
    122 {
    123 
    124     //【1】读取图像
    125     Mat srcImage4= imread("dota_pa.jpg",1);
    126     Mat logoImage= imread("dota_logo.jpg");
    127 
    128     if( !srcImage4.data ) { printf("读取srcImage4错误~! 
    "); return false; }
    129     if( !logoImage.data ) { printf("读取logoImage错误~! 
    "); return false; }
    130 
    131     //【2】定义一个Mat类型并给其设定ROI区域
    132     Mat imageROI;
    133     //方法一
    134     imageROI= srcImage4(Rect(200,250,logoImage.cols,logoImage.rows));
    135     //方法二
    136     //imageROI= srcImage4(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));
    137 
    138     //【3】将logo加到原图上
    139     addWeighted(imageROI,0.5,logoImage,0.3,0.,imageROI);
    140 
    141     //【4】显示结果
    142     imshow("<4>区域线性图像混合示例窗口",srcImage4);
    143 
    144     return true;
    145 }

    分离颜色通道、多通道图像混合

    通道分离:split函数

    split函数用于将一个多通道数组分离成几个单通道数组,这里的array用语境翻译为数组或者阵列。

    两个原型:

    1 void split(const Mat& src, Mat*mvbegin);
    2 void split(inputarray m, outputarrayofarrays mv);

    (1)src、m是需要进行分离的多通道数组

    (2)mv是函数的输出数组或者输出的vector容器

     1 Mat imageBlueChannel;
     2 Mat imageGreenChannel;
     3 Mat imageRedChannel;
     4 vector<Mat> channels;
     5 
     6 srcImge4 = imread("dota.jpg");
     7 split(srcImage4,channels);//分离色彩通道
     8 
     9 //把载入的三通道图像转换到三个单通道图像,放到vector<Mat>类型的channel中
    10 imageBlueChannel = channels.at(0);
    11 imageGreenChannel = channels.at(1);
    12 imageRedChannel = channels.at(2);

    通道合并:merge函数

    两个原型:

    1 void merge(const Mat* mv, size_tcount, OutputArray dst);
    2 void merge(inputarrayofarrays mv, outputarray dst);

    (1)mv,需要被合并的输入矩阵或vector容器的阵列,这个mv参数中所有矩阵必须有一样的尺寸和深度。

    (2)count,当mv为空白的C数组时,代表输入矩阵的个数,这个参数显然必须大于1

    (3)dst,输出矩阵,和mv[0]有一样的尺寸,并且通道的数量是矩阵阵列中的通道的总数

    merge函数将一些数组合并成一个多通道数组。第i个输入数组的元素被视为mv[i]。C一般用一中的Mat::at()函数对某个通道进行存取,channels.at(0)。

    Mat::at()方法返回一个引用到指定的数组元素。注意是引用,相当于两者等价

      1 //-----------------------------------【头文件包含部分】---------------------------------------
      2 //    描述:包含程序所依赖的头文件
      3 //------------------------------------------------------------------------------------------------                                                                                     
      4 #include <opencv2/core/core.hpp>
      5 #include <opencv2/highgui/highgui.hpp>
      6 #include <iostream>
      7 
      8 //-----------------------------------【命名空间声明部分】---------------------------------------
      9 //    描述:包含程序所使用的命名空间
     10 //-------------------------------------------------------------------------------------------------   
     11 using namespace cv;
     12 using namespace std;
     13 
     14 
     15 //-----------------------------------【全局函数声明部分】--------------------------------------
     16 //    描述:全局函数声明
     17 //-----------------------------------------------------------------------------------------------
     18 bool  MultiChannelBlending();
     19 void ShowHelpText();
     20 
     21 
     22 //-----------------------------------【main( )函数】------------------------------------------
     23 //    描述:控制台应用程序的入口函数,我们的程序从这里开始
     24 //-----------------------------------------------------------------------------------------------
     25 int main(   )
     26 {
     27     system("color 9F");
     28 
     29     ShowHelpText( );
     30 
     31     if(MultiChannelBlending( ))
     32     {
     33         cout<<endl<<"
    运行成功,得出了需要的图像~! ";
     34     }
     35 
     36     waitKey(0);
     37     return 0;
     38 }
     39 
     40 
     41 
     42 //-----------------------------------【ShowHelpText( )函数】----------------------------------
     43 //         描述:输出一些帮助信息
     44 //----------------------------------------------------------------------------------------------
     45 void ShowHelpText()
     46 {
     47     //输出欢迎信息和OpenCV版本
     48     printf("
    
    			非常感谢购买《OpenCV3编程入门》一书!
    ");
     49     printf("
    
    			此为本书OpenCV3版的第26个配套示例程序
    ");
     50     printf("
    
    			   当前使用的OpenCV版本为:" CV_VERSION );
     51     printf("
    
      ----------------------------------------------------------------------------
    ");
     52 }
     53 
     54 
     55 
     56 
     57 
     58 
     59 //-----------------------------【MultiChannelBlending( )函数】--------------------------------
     60 //    描述:多通道混合的实现函数
     61 //-----------------------------------------------------------------------------------------------
     62 bool  MultiChannelBlending()
     63 {
     64     //【0】定义相关变量
     65     Mat srcImage;
     66     Mat logoImage;
     67     vector<Mat> channels;
     68     Mat  imageBlueChannel;
     69 
     70     //=================【蓝色通道部分】=================
     71     //    描述:多通道混合-蓝色分量部分
     72     //============================================
     73 
     74     // 【1】读入图片
     75     logoImage= imread("dota_logo.jpg",0);//灰度图是因为,我们是对一个通道进行线性加权的,所以也要将logoimage变成一个通道
     76     srcImage= imread("dota_jugg.jpg");
     77 
     78     if( !logoImage.data ) { printf("Oh,no,读取logoImage错误~! 
    "); return false; }
     79     if( !srcImage.data ) { printf("Oh,no,读取srcImage错误~! 
    "); return false; }
     80 
     81     //【2】把一个3通道图像转换成3个单通道图像
     82     split(srcImage,channels);//分离色彩通道
     83 
     84     //【3】将原图的蓝色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
     85     imageBlueChannel= channels.at(0);
     86     //【4】将原图的蓝色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageBlueChannel中
     87     addWeighted(
     88                 imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)),//需要加权的第一个数组
     89                 1.0,//第一个数组的权重
     90                 logoImage,//第二个数组,和第一个数组有相同的尺寸和通道数
     91                 0.5//第二个数组的权重
     92                 0,//gamma,加到权重总和上的标量值
     93                 imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows))
     94                 );
     95 
     96     //【5】将三个单通道重新合并成一个三通道
     97     merge(channels,srcImage);
     98 
     99     //【6】显示效果图
    100     namedWindow(" <1>游戏原画+logo蓝色通道");
    101     imshow(" <1>游戏原画+logo蓝色通道",srcImage);
    102 
    103 
    104     //=================【绿色通道部分】=================
    105     //    描述:多通道混合-绿色分量部分
    106     //============================================
    107 
    108     //【0】定义相关变量
    109     Mat  imageGreenChannel;
    110 
    111     //【1】重新读入图片
    112     logoImage= imread("dota_logo.jpg",0);
    113     srcImage= imread("dota_jugg.jpg");
    114 
    115     if( !logoImage.data ) { printf("读取logoImage错误~! 
    "); return false; }
    116     if( !srcImage.data ) { printf("读取srcImage错误~! 
    "); return false; }
    117 
    118     //【2】将一个三通道图像转换成三个单通道图像
    119     split(srcImage,channels);//分离色彩通道
    120 
    121     //【3】将原图的绿色通道的引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
    122     imageGreenChannel= channels.at(1);
    123     //【4】将原图的绿色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageGreenChannel中
    124     addWeighted(imageGreenChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,
    125         logoImage,0.5,0.,imageGreenChannel(Rect(500,250,logoImage.cols,logoImage.rows)));
    126 
    127     //【5】将三个独立的单通道重新合并成一个三通道
    128     merge(channels,srcImage);
    129 
    130     //【6】显示效果图
    131     namedWindow("<2>游戏原画+logo绿色通道");
    132     imshow("<2>游戏原画+logo绿色通道",srcImage);
    133 
    134 
    135 
    136     //=================【红色通道部分】=================
    137     //    描述:多通道混合-红色分量部分
    138     //============================================
    139 
    140     //【0】定义相关变量
    141     Mat  imageRedChannel;
    142 
    143     //【1】重新读入图片
    144     logoImage= imread("dota_logo.jpg",0);
    145     srcImage= imread("dota_jugg.jpg");
    146 
    147     if( !logoImage.data ) { printf("Oh,no,读取logoImage错误~! 
    "); return false; }
    148     if( !srcImage.data ) { printf("Oh,no,读取srcImage错误~! 
    "); return false; }
    149 
    150     //【2】将一个三通道图像转换成三个单通道图像
    151     split(srcImage,channels);//分离色彩通道
    152 
    153     //【3】将原图的红色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
    154     imageRedChannel= channels.at(2);
    155     //【4】将原图的红色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageRedChannel中
    156     addWeighted(imageRedChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,
    157         logoImage,0.5,0.,imageRedChannel(Rect(500,250,logoImage.cols,logoImage.rows)));
    158 
    159     //【5】将三个独立的单通道重新合并成一个三通道
    160     merge(channels,srcImage);
    161 
    162     //【6】显示效果图
    163     namedWindow("<3>游戏原画+logo红色通道 ");
    164     imshow("<3>游戏原画+logo红色通道 ",srcImage);
    165 
    166     return true;
    167 }

    图像对比度、亮度调整

    一般图像处理算子都是一个函数,接受一个或多个输入图像,并产生输出图像,下面是算子的一般形式:

    图像对比度和亮度的操作,属于比较简单的一种--点操作。点操作的特点:仅仅根据输入像素值,来计算相应的输出像素值。这列算子包括亮度(brightness)、对比度(constrast)、颜色校正(colorcorrection)、变换(transformations)。

    两种最常用的点操作(点算子)是乘上一个常数(对比度的调节)再加上一个常数(对应亮度的调节),公式如下:

    (1)f(x)表示源图像像素;

    (2)g(x)表示输出图像像素

    (3)a>0,增益,控制对比度

    (4)b,偏置,控制亮度

     进一步可以改写成:

    访问图片中的像素

     1 //三个for循环执行运算: new_image(i,j) = a*image(i,j) + b
     2 for(int y = 0; y < image.rows; y++)
     3 {
     4     for(int x = 0; x < image.cols; x++)
     5     {
     6         for(int c = 0; c < 3,; c++)
     7         {
     8             new_image.at<vector>(y,x)[c] = saturate_cast<uchar>( 
     9             (g_nContrastValue*0.01) * (image.at<vector>(y,x)[c]) + g_nBrightValue
    10             )
    11         }
    12     }
    13 }

    访问图像的每一个像素,使用的语法为:image.at<vector>(y,x)[c]

    因为计算结果可能会超出像素取值范围(溢出),还可能是非整数,所以用saturate_cast对结果进行转换,确保是有效值。saturate_cast模板函数,用于溢出保护,大致原理如下:

    1 if(data<0)
    2     data = 0;
    3 else if(data > 255)
    4     data=255;

    示例程序:图像对比度、亮度调节

      1 //--------------------------------------【程序说明】-------------------------------------------
      2 //        程序说明:《OpenCV3编程入门》OpenCV3版书本配套示例程序27
      3 //        程序描述:图像对比度、亮度值调整
      4 //        开发测试所用IDE版本:Visual Studio 2010
      5 //        开发测试所用OpenCV版本:    3.0 beta
      6 //        2014年11月 Created by @浅墨_毛星云
      7 //        2014年12月 Revised by @浅墨_毛星云
      8 //------------------------------------------------------------------------------------------------
      9 
     10 
     11 
     12 //-----------------------------------【头文件包含部分】---------------------------------------
     13 //    描述:包含程序所依赖的头文件
     14 //---------------------------------------------------------------------------------------------- 
     15 #include <opencv2/core/core.hpp>
     16 #include <opencv2/highgui/highgui.hpp>
     17 #include "opencv2/imgproc/imgproc.hpp"
     18 #include <iostream>
     19 
     20 //-----------------------------------【命名空间声明部分】---------------------------------------
     21 //    描述:包含程序所使用的命名空间
     22 //-----------------------------------------------------------------------------------------------   
     23 using namespace std;
     24 using namespace cv;
     25 
     26 
     27 //-----------------------------------【全局函数声明部分】--------------------------------------
     28 //    描述:全局函数声明
     29 //-----------------------------------------------------------------------------------------------
     30 static void ContrastAndBright(int, void *);
     31 void   ShowHelpText();
     32 
     33 //-----------------------------------【全局变量声明部分】--------------------------------------
     34 //    描述:全局变量声明
     35 //-----------------------------------------------------------------------------------------------
     36 int g_nContrastValue; //对比度值
     37 int g_nBrightValue;  //亮度值
     38 Mat g_srcImage,g_dstImage;
     39 //-----------------------------------【main( )函数】--------------------------------------------
     40 //    描述:控制台应用程序的入口函数,我们的程序从这里开始
     41 //-----------------------------------------------------------------------------------------------
     42 int main(   )
     43 {
     44     //改变控制台前景色和背景色
     45     system("color 2F");  
     46 
     47     ShowHelpText();
     48     // 读入用户提供的图像
     49     g_srcImage = imread( "1.jpg");
     50     if( !g_srcImage.data ) { printf("读取g_srcImage图片错误~! 
    "); return false; }
     51     //创建和输入图像一样size和type的全零矩阵
     52     g_dstImage = Mat::zeros( g_srcImage.size(), g_srcImage.type() );
     53 
     54     //设定对比度和亮度的初值
     55     g_nContrastValue=80;
     56     g_nBrightValue=80;
     57 
     58     //创建窗口
     59     namedWindow("【效果图窗口】", 1);
     60 
     61     //创建轨迹条
     62     createTrackbar("对比度:",//轨迹条名字
     63                     "【效果图窗口】",//窗口名字
     64                     &g_nContrastValue, //对比度当前值
     65                     300,//对比度最大值
     66                     ContrastAndBright//回调函数
     67                     );
     68     createTrackbar("亮   度:", "【效果图窗口】",&g_nBrightValue, 200,ContrastAndBright );
     69 
     70     //调用回调函数,viod* 默认用0
     71     ContrastAndBright(g_nContrastValue,0);//为什么是0???
     72     ContrastAndBright(g_nBrightValue,0);
     73 
     74     //输出一些帮助信息
     75     cout<<endl<<"	运行成功,请调整滚动条观察图像效果
    
    "
     76         <<"	按下“q”键时,程序退出
    ";
     77 
     78     //按下“q”键时,程序退出
     79     while(char(waitKey(1)) != 'q') {}
     80     return 0;
     81 }
     82 
     83 
     84 
     85 
     86 //-----------------------------------【ShowHelpText( )函数】----------------------------------
     87 //         描述:输出一些帮助信息
     88 //----------------------------------------------------------------------------------------------
     89 void ShowHelpText()
     90 {
     91     //输出欢迎信息和OpenCV版本
     92     printf("
    
    			非常感谢购买《OpenCV3编程入门》一书!
    ");
     93     printf("
    
    			此为本书OpenCV3版的第27个配套示例程序
    ");
     94     printf("
    
    			   当前使用的OpenCV版本为:" CV_VERSION );
     95     printf("
    
      ----------------------------------------------------------------------------
    ");
     96 }
     97 
     98 
     99 //-----------------------------【ContrastAndBright( )函数】------------------------------------
    100 //    描述:改变图像对比度和亮度值的回调函数
    101 //-----------------------------------------------------------------------------------------------
    102 static void ContrastAndBright(int, void *)
    103 {
    104 
    105     // 创建窗口
    106     namedWindow("【原始图窗口】", 1);
    107 
    108     // 三个for循环,执行运算 g_dstImage(i,j) = a*g_srcImage(i,j) + b
    109     for( int y = 0; y < g_srcImage.rows; y++ )
    110     {
    111         for( int x = 0; x < g_srcImage.cols; x++ )
    112         {
    113             for( int c = 0; c < 3; c++ )
    114             {
    115                 g_dstImage.at<Vec3b>(y,x)[c] = saturate_cast<uchar>( (g_nContrastValue*0.01)*( g_srcImage.at<Vec3b>(y,x)[c] ) + g_nBrightValue );
    116             }
    117         }
    118     }
    119 
    120     // 显示图像
    121     imshow("【原始图窗口】", g_srcImage);
    122     imshow("【效果图窗口】", g_dstImage);
    123 }

    离散傅里叶变换DFT

    指傅里叶变换在时域和频域上都呈现离散的形式,将时域信号的采样变换为在离散时间傅里叶变换(DTFT)频域的采样。

    对有限长的离散信号做DFT,也应当对其经过周期延拓成周期信号再进行变换。

    实际应用中,通常采用快速傅里叶变换来高效计算DFT。

    原理

    对一张图像使用傅里叶变换就是将它分解成正弦和余弦的和的形式。傅里叶变换的作用实际上就是函数分解的工具。

    二维图像傅里叶变换公式:

    转换之后的频域值是复数,因此结果使用实数图像+虚数图像,或者幅度图像+相位图像。

    实际图像处理过程中,仅仅使用幅度图像,幅度图像包含了原图像几乎所有我们需要的几何信息。如果想通过修改幅度图像或者相位图像来间接修改原空间图像,需要使用逆傅里叶变换得到修改后的空间图像。

    频域里面,对于一幅图像,高频部分代表了图像的细节、纹理信息;低频部分代表了图像的轮廓信息。

    如果图像受到的噪声位于某个特定的频率范围之内,则可以通过滤波器来恢复原来的图像。

    傅里叶变换在图像处理中可以做到图像增强和图像去燥,图像分割之边缘检测、图像特征提取,图像压缩等。

     dft函数

    dft函数是对一维或二维浮点数数组进行正向或反向离散傅里叶变换。

    1 void dft(inputarray src, outputarray dst, int flags=0, int nonzeroRows=0);

    (1)src,输入矩阵,实数或虚数

    (2)dst,运算结果,尺寸和类型取决于标识符,也就是flags

    (3)flags,转换标识符,默认0

    (4)nonzeroRows,默认值0。

  • 相关阅读:
    2019-2020-2 网络对抗技术 20175213吕正宏 Exp4 恶意代码分析
    2019-2020-2 网络对抗技术 20175213吕正宏 Exp3 免杀原理与实践
    2019-2020-2 网络对抗技术 20175213吕正宏 Exp2 后门原理与实践
    2019-2020-2 网络对抗技术 20175213吕正宏 Exp1 PC平台逆向破解
    ucosii-2(选做)
    2019-2020-2 网络对抗技术 20175224 Exp9 Web安全基础
    2019-2020-2 网络对抗技术 20175224 Exp8 Web基础
    2019-2020-2 网络对抗技术 20175224 Exp7 网络欺诈防范
    2019-2020-2 网络对抗技术 20175224 Exp6 MSF基础应用
    2019-2020-2 网络对抗技术 20175224 Exp5 信息搜集与漏洞扫描
  • 原文地址:https://www.cnblogs.com/pacino12134/p/10980325.html
Copyright © 2011-2022 走看看