opencv图像处理基础 (《OpenCV编程入门--毛星云》学习笔记一---五章)

#include 
#include 
#include 
#include 

using namespace cv;



int main()
{
  Mat Valley = imread("/home/ttwang/Valley.jpg");
  Mat ValleyLogo = imread("/home/ttwang/ValleyLogo.jpg");
  namedWindow("[1] ValleyPic");
  imshow("[1] ValleyPic",Valley);
  namedWindow("[2] ValleyLogo");
  imshow("[2] ValleyLogo",ValleyLogo);
  Mat valleyROI;

/******************实现两个图像混合****************************/
valleyROI
= Valley(Rect(800,350,ValleyLogo.cols,ValleyLogo.rows)); addWeighted(valleyROI,0.5,ValleyLogo,0.3,0.,valleyROI); namedWindow("valley+logo"); imshow("valley+logo",Valley); // imwrite("",Valley); waitKey(0); return 0; }



二、创建滑动条:createTrackbar()函数  (利用滑动条实现两幅图的Alpha混合

 1 #include   //本人所用的IDE是QT,,终端编译时不需要该声明
 2 #include 
 3 #include 
 4 #include 
 5 using namespace cv;
 6 
 7 #define WINDOW_NAME "[Alpha]"   //窗口名的宏定义
 8 
 9 const int g_nMaxAlphaValue = 100;
10 int g_nAlphaValueSlider;
11 double g_dAlphaValue;
12 double g_dBetaValue;
13 
14 Mat g_srcImage1;
15 Mat g_srcImage2;
16 Mat g_dstImage;
17 /**********响应滑动条的回调函数*************/
18 void on_Trackbar( int ,void*)
19 {
20     g_dAlphaValue = (double) g_nAlphaValueSlider/g_nMaxAlphaValue;
21     g_dBetaValue = (1.0 - g_dAlphaValue);
22     //根据Alpha beta的值进行线性混合
    addWeighted(g_srcImage1,g_dAlphaValue,g_srcImage2,g_dBetaValue,0.0,g_dstImage); 23 imshow(WINDOW_NAME,g_dstImage); 24 } 25 26 int main() 27 { 28 g_srcImage1 = imread("/home/ttwang/11.jpg");  //两幅图的尺寸要相同,否则出现如下图错误 29 g_srcImage2 = imread("/home/ttwang/12.jpg"); 30 31 g_nAlphaValueSlider = 70; 32 namedWindow(WINDOW_NAME,1); 33 34 char TrackbarName[50]; 35 sprintf(TrackbarName,"透明值 %d", g_nMaxAlphaValue); 36 createTrackbar(TrackbarName,WINDOW_NAME, &g_nAlphaValueSlider, g_nMaxAlphaValue,on_Trackbar); 37 on_Trackbar(g_nAlphaValueSlider,0); 38 39 waitKey(0); 40 return 0; 41 42 }

opencv图像处理基础 (《OpenCV编程入门--毛星云》学习笔记一---五章)_第1张图片

 由于程序不是直接粘贴过来的,按该程序进行编译时候,总出现错误,可以参考下面的链接  感谢分享





 

 

三、鼠标操作:SetMouseCallback()函数

 

#include 
#include 
#include 
#include 
using namespace cv;

#define WINDOW_NAME "[Program window]"   //为窗口标题定义的宏

/******************全局函数的声明********************/
void on_MouseHandle(int event,int x, int y, int flags, void* param);
void DrawRectangle(cv::Mat& img, cv::Rect box);
void ShowHelpText();

/******************全局变量声明*********************/
Rect g_rectangle;
bool g_bDrawingBox = false;//是否绘制
RNG g_rng(12345);



int main()
{
  g_rectangle = Rect(-1,-1,0,0);
  Mat srcImage(600,800,CV_8UC3),tempImage;
  srcImage.copyTo(tempImage);
  g_rectangle = Rect(-1,-1,0,0);
  srcImage = Scalar::all(0);

  //设置鼠标操作回调函数
  namedWindow(WINDOW_NAME);
  setMouseCallback(WINDOW_NAME,on_MouseHandle,(void*)&srcImage);
  while(1)
  {
     srcImage.copyTo(tempImage);  //复制源图到临时变量
     if(g_bDrawingBox) DrawRectangle(tempImage,g_rectangle);//当绘制标识符为真,进行绘制
     imshow(WINDOW_NAME,tempImage);
     if(waitKey(10) == 27) break;    //按下Esc,程序退出
  }
   return 0;
}

/*********鼠标回调函数,根据不同的鼠标事件进行不同的操作*******************/
void on_MouseHandle(int event, int x, int y, int flags, void *param)
{
    Mat& image = *(cv::Mat*) param;
    switch (event)
    {
      //鼠标移动消息
      case EVENT_MOUSEMOVE:
      {
        if(g_bDrawingBox)//如果是否进行绘制额标识符为真,则记录下长和宽到RECT型变量中
        {
            g_rectangle.width = x - g_rectangle.x;
            g_rectangle.height = y- g_rectangle.y;
        }
      }
        break;
      //左键按下消息
      case EVENT_LBUTTONDOWN:
      {
          g_bDrawingBox = true;
          g_rectangle = Rect(x,y,0,0);//记录起始点
      }
        break;
      //左键抬起消息
      case EVENT_LBUTTONUP:
      {
          g_bDrawingBox = false;  //置标识符为false
          //对宽和高小于0的进行处理
          if(g_rectangle.width < 0)
          {
              g_rectangle.x += g_rectangle.width;
              g_rectangle.width *= -1;
          }
          if(g_rectangle.height < 0)
          {
              g_rectangle.y += g_rectangle.height;
              g_rectangle.height *= -1;
          }
          //调用回调函数进行绘制
          DrawRectangle( image, g_rectangle);
      }
        break;

    }
}

/********************自定义的矩形绘制函数DrawRectangle() ********************/
void DrawRectangle(cv::Mat& img, cv::Rect box)
{
    rectangle(img,box.tl(),box.br(),Scalar(g_rng.uniform(0,255),g_rng.uniform(0,255),g_rng.uniform(0,255)));
}



 四章、OpenCV数据结构与基本绘图

1. Mat M(2,2,CV_8UC3,Scalar(0,0,255)); //使用Mat()构造函数创建Mat对象

 两行两列、CV_8UC3: CV_[位数][带符号与否]C[通道数] Scalar是个short类型的向量,可以使用指定的值来初始化矩阵

2.Mat M;  M.create(4,4,CV_8UC3);  //使用create()函数创建Mat对象,,此方法不能为矩阵设初值

3.颜色的表示类:Scalar()是具有四个元素的数组,,第四个用不到,则不写 格式如下:

        Scalar(a, b,  c)定义的RGB颜色值:红色分量c 绿色分量b  蓝色分量 a

4.尺寸的表示类: Size()  常用格式: Size(5,5)表示构造出的Size高度和宽度都为5

5.矩形的表示类: Rect类的成员有x,y,width,height,分别为左上角的坐标和矩形的宽、高

         格式: Rect rect(0,0,200,400)

6.颜色空间转换:cvtColor()函数  格式:cvtColor(InputArraysrc, OutputArray dst, int code, int dstCn=0) 

                 第一个参数:输入图像;

                 第二个参数:输出图像;

                 第三个参数:颜色空间转换的标识符; (详见:P98)

                                                                第四个参数:目标图像的通道数,若为0,则表示其取源图像的通道数。

7.基本图型的绘制涉及的函数:   (通过例程学习 P100) 

              绘制直线的line函数

              绘制椭圆的ellipse函数

              绘制矩形的rectangle函数

              绘制圆的circle函数

              绘制填充的多边形的fillPloy函数


 

第五章 core组件进阶

1.计时函数:  getTickCount()和getTickFrequency()

       getTickCount()函数返回CPU自某个事件以来走过的时钟周期数

       getTickFrequency()函数返回CPU一秒钟走过的周期数

显然: 二者结合可以实现对某种图像处理方法的计时

double time0 = static_cast<double>(getTickCount());  //记录起始时间

time0= ((double)getTickCount() - time0)/getTickFrequency();////计算运行时间并输出

cout<<"\t此方法运行时间为:"<""<//输出运行时间

 

2.访问图像中像素的几种方法 (简单介绍,具体P110)

需要先明白以下知识: 

(1) Mat类的公有成员变量cols和rows给出了图像的宽和高

   image.cols       image.rows

(2)    Mat类的成员函数channels()用于返回图像的通道数;

  灰度图像通道数1,彩色图像通道数为3  image.channels()

(4)    每一行的像素个数= image.cols*image.channels()       

a.直接遍历,使用Mat里的成员函数data

/*********只用于访问连续空间********/
Mat mat (3000,4000,CV_8UC3)
int es = mat.eleSize();   //定义步长,因为定义为3通道的,实质该值为3
int size = mat.rows*mat.cols*es;
for(int i = 0; i < size; i += es)
{
  mat.data[i] = 255;     // B通道
  mat.data[i+1] = 0;    // G通道
  mat.data[i+2] = 0;   //  R通道
}

b.直接访问不连续空间

for (int row = 0; row < mat.rows; row++)
{
for (int col = 0; col < mat.cols; col++)
{
(&mat.data[row*mat.step])[col*es] = 0;
(&mat.data[row*mat.step])[col*es + 1] = 0;
(&mat.data[row*mat.step])[col*es + 2] = 255;
}
}

c.通过opencv ptr模板函数遍历

 1 for (int row = 0; row < mat.rows; row++)
 2 {
 3   for (int col = 0; col < mat.cols; col++)
 4   {
 5      Vec3b *c = mat.ptr(row,col);
 6      c->val[0] = 0;
 8      c->val[1] = 255
10      c->val[2] = 0;
    }
13 }

c.通过at遍历

 1   for (int row = 0; row < mat.rows; row++)
 2  {
 3     for (int col = 0; col < mat.cols; col++)
 4    {
 5       Vec3b &m = mat.at(row, col);
 6       m[0] = 0;
 7       m[1] = 0;
 8       m[2] = 255;
 9    }
10 }

 d.通过迭代器遍历

1   auto it = mat.begin();   //自动类型匹配auto
2   auto it_end = mat.end();
3   for (; it != it_end; it++)
4   {
5    (*it).val[0] = 0;
6    (*it).val[1] = 0;
7    (*it).val[2] = 255;
8   }

 

3.感兴趣区域ROI

/******表示方法一 Rect矩形区域*******/

Mat imageROI
imageROI = image(Rect(500,250,logo.cols,logo.rows));  //image为已经载入好的图片

/******表示方法二 Range指定感兴趣的行和列********/

imageROI = image(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols)); //image为已经载入好的图片
 
4.利用addWeighted可实现图像线性混合
数学公式: dst = src1[I] * alpha + src2[I]*beta + gamma      (P117)
5.分离颜色通道、多通道图像混合
通道分离:split()函数,将一个3通道图像转换成3个单通道
通道合并:merge()函数

###例程:(课本P127,以多通道混合-蓝色分量部分为例)
###平台:QT5.7.1+OpenCV3.2.0
###时间:2017年12月11日

/********建立QT控制台程序*********/
#include 
#include 
#include 
#include 
#include 
using namespace std;
using namespace cv;

//全局函数声明
bool MultiChannelBlending();


int main()
{
    if(MultiChannelBlending())
    {
        cout << endl << "\n运行成功,得到目标图像" << endl;
    }
    waitKey(0);
    return 0;
}
/*********多通道混合的实现函数*********/
bool MultiChannelBlending()
{
    Mat srcImage;
    Mat logoImage;
    vector channels;
    /********** 蓝色分量 *************/
    Mat imageBlueChannel;
    logoImage = imread("/home/ttwang/Valley_logo.jpg",0);//一定要读入会灰度图像,不然addWeighted()会因为类型不匹配而报错
    srcImage = imread("/home/ttwang/Valley.jpg");
    split(srcImage,channels); //将一个3通道图像转换成3个单通道
    imageBlueChannel = channels.at(0); //将原图的蓝色通道引用返回给imageBlueChannel
    addWeighted(imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.,imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)));
    merge(channels,srcImage);//将三个单通道重新合并成一个三通道
    namedWindow("src+LogoBlue");
    imshow("src+LogoBlue",srcImage);


    /*******绿色分量 ******/
     Mat imageGreenChannel;
     logoImage = imread("/home/ttwang/Valley_logo.jpg",0);
     srcImage = imread("/home/ttwang/Valley.jpg");
     split(srcImage,channels); //将一个3通道图像转换成3个单通道
     imageGreenChannel = channels.at(1);
     addWeighted(imageGreenChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.0,imageGreenChannel(Rect(500,250,logoImage.cols,logoImage.rows)));
     merge(channels,srcImage);//将三个单通道重新合并成一个三通道
     namedWindow("src+LogoGreen");
     imshow("src+LogoGreen",srcImage);

     /*******红色分量 ******/
      Mat imageRedChannel;
      logoImage = imread("/home/ttwang/Valley_logo.jpg",0);
      srcImage = imread("/home/ttwang/Valley.jpg");
      split(srcImage,channels); //将一个3通道图像转换成3个单通道
      imageRedChannel = channels.at(2);
      addWeighted(imageRedChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.0,imageRedChannel(Rect(500,250,logoImage.cols,logoImage.rows)));
      merge(channels,srcImage);//将三个单通道重新合并成一个三通道
      namedWindow("src+LogoRed");
      imshow("src+LogoRed",srcImage);
      return true;
}

 

6.图像对比度、亮度调整

公式: g(i,j)=a*f(i,j)+b;    (opencv控制图像对比度和亮度的理论公式)

        参数a(a>0)通常被成为增益,控制图像的对比度
        参数b称为偏置,控制图像的亮度

访问图片中的像素:(使用三个for循环,语法:image.at(y,x)[c])
其中,y是像素所在的行,x是像素所在的列,c是B、G、 R(对应0、12

 

7.离散傅里叶变换(详细参照课本P135)
  参考资料及函数说明,参照下面的链接:  opencv2教程之离散型傅里叶变换

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/ilym/p/7993956.html

你可能感兴趣的:(opencv图像处理基础 (《OpenCV编程入门--毛星云》学习笔记一---五章))