天天看点

六、OpenCV学习笔记——常用函数解析

一、Mat

Mat是OpenCV里最基本的一个类,用来表示图像。

// 默认构造函数 Mat A;
    Mat ()
    // 常用构造函数 Mat A(10,10,8UC3);
    Mat (int rows, int cols, int type)

    //Mat A(300, 400, CV_8UC3,Scalar(255,255,255));
    Mat (int ndims, const int *sizes, int type, const Scalar &s)

    Mat (Size size, int type)

    Mat (int rows, int cols, int type, const Scalar &s)

    Mat (Size size, int type, const Scalar &s)

    Mat (int ndims, const int *sizes, int type)

    Mat (const Mat &m)

    Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)

    Mat (Size size, int type, void *data, size_t step=AUTO_STEP)

    Mat (int ndims, const int *sizes, int type, void *data, const size_t *steps=0)

    Mat (const Mat &m, const Range &rowRange, const Range &colRange=Range::all())

    //Mat D (A, Rect(10, 10, 100, 100) );
    Mat (const Mat &m, const Rect &roi)

    Mat (const Mat &m, const Range *ranges)
           

可以参考以下博文:

https://blog.csdn.net/u010248552/article/details/79962132

二、访问像素方式

1)指针方式

坐标的指针:

void colorReduce(const Mat& image,Mat& outImage,int div)  
{  
    int nr=image.rows;  
    int nc=image.cols;  
    outImage.create(image.size(),image.type());  
    if(image.isContinuous()&&outImage.isContinuous())  
    {  
        nr=1;  
        nc=nc*image.rows*image.channels();  
    }  
    for(int i=0;i<nr;i++)  
    {   //行指针
        const uchar* inData=image.ptr<uchar>(i);  
        uchar* outData=outImage.ptr<uchar>(i);  
        for(int j=0;j<nc;j++)  
        {  //列指针
            *outData++=*inData++/div*div+div/2;  
        }  
    }  
}
           

数据的指针:

//三通道
	uchar *data = image.data ;
	for(int h = 0 ; h < image.rows ; ++ h)
	{
		for(int w = 0 ; w < image.cols/2 ; ++ w)
		{
			*data ++ = 128 ;
			*data ++ = 128 ;
			*data ++ = 128 ;
		}
	}
	imshow("data" , image) ;
	//单通道
	image = imread("forest.jpg" , 0) ;
	imshow("image" , image) ;
 
	data = image.data ;
	for(int h = 0 ; h < image.rows ; ++ h)
	{
		for(int w = 0 ; w < image.cols/2 ; ++ w)
		{
			*data ++ = 128 ;
		}
	}
           

2)at方式

at方式相当于直接访问像素坐标:

void colorReduce(Mat& image,int div)  
{  
    for(int i=0;i<image.rows;i++)  
    {  
        for(int j=0;j<image.cols;j++)  
        {  
            image.at<Vec3b>(i,j)[0]=image.at<Vec3b>(i,j)[0]/div*div+div/2;  
            image.at<Vec3b>(i,j)[1]=image.at<Vec3b>(i,j)[1]/div*div+div/2;  
            image.at<Vec3b>(i,j)[2]=image.at<Vec3b>(i,j)[2]/div*div+div/2;  
        }  
    }  
} 
           

3)迭代器访问

迭代器就是通过获得图像矩阵的开始和结束,然后增加迭代直至从开始到结束:

cv::Mat tempImage = srcImage.clone();  
    // 初始化源图像迭代器  
    cv::MatConstIterator_<cv::Vec3b> srcIterStart  = srcImage.begin<cv::Vec3b>();  
    cv::MatConstIterator_<cv::Vec3b> srcIterEnd = srcImage.end<cv::Vec3b>();  
    // 初始化输出图像迭代器  
    cv::MatIterator_<cv::Vec3b> resIterStart = tempImage.begin<cv::Vec3b>();  
    cv::MatIterator_<cv::Vec3b> resIterEnd = tempImage.end<cv::Vec3b>();  
    // 遍历图像反色处理  
    while( srcIterStart != srcIterEnd )  
    {  
         (*resIterStart)[0] = 255 - (*srcIterStart)[0];  
         (*resIterStart)[1] = 255 - (*srcIterStart)[1];  
         (*resIterStart)[2] = 255 - (*srcIterStart)[2];  
         // 迭代器递增  
         srcIterStart++;  
         resIterStart++;  
    }  
           

4)查找表函数

可以根据查找表的映射来进行像素的变换:

cv::Mat inverseColor6(cv::Mat srcImage)  
{  
    int row = srcImage.rows;  
    int col = srcImage.cols;  
    cv::Mat tempImage = srcImage.clone();  
    // 建立LUT 反色table  
    uchar LutTable[256];  
    for (int i = 0; i < 256; ++i)  
       LutTable[i] = 255 - i;  
    cv::Mat lookUpTable(1, 256, CV_8U);  
    uchar* pData = lookUpTable.data;   
    // 建立映射表  
    for( int i = 0; i < 256; ++i)  
        pData[i] = LutTable[i];  
    // 应用索引表进行查找  
    cv::LUT(srcImage, lookUpTable, tempImage);  
    return tempImage;  
} 
           

可以参考以下博文:

https://blog.csdn.net/qq_20823641/article/details/51920846

三、感兴趣区域(ROI)

ROI允许我们选取图像特定的区域进行操作,有两种方式。

1)使用矩形(Rect)类

Mat  ROI;
ROI=image(Rect_ (_Tp _x, _Tp _y, _Tp _width, _Tp _height));
    x,y这两个参数就是矩形区域左上角的坐标
    width,height这两个参数就是矩形局域的宽和高
           

2)手动指定感兴趣的行和列的范围

Mat  ROI;
ROI=image(Rect_ (range(row_start,row_end),range(col_strat,col_end)));
    range(row_start,row_end):行的开始和结束
    range(col_strat,col_end):列的开始和结束
           

可以参考以下博文:

https://blog.csdn.net/xierhacker/article/details/52493746

四、绘制直方图

计算直方图:

void calcHist(const Mat* arrays, intnarrays, const int* channels, InputArray mask, OutputArray 
hist, int dims,const int* histSize, const float** ranges, bool uniform=true, boolaccumulate=false );
           
参数解释:
  • arrays:输入的图像的指针,可以是多幅图像,所有的图像必须有同样的深度,一副图像可以有多个channes。
  • narrays:输入的图像的个数。
  • channels:用来计算直方图的channes的数组。比如输入是2副图像,第一副图像有0,1,2共三个channel,第二幅图像只有0一个channel,那么输入就一共有4个channes,如果int

    channels[3] = {3, 2, 0},那么就表示是使用第二副图像的第一个通道和第一副图像的第2和第0个通道来计算直方图。

  • mask:掩码。如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和arrays[i]的大小相同,值为1的点将用来计算直方图。
  • hist:计算出来的直方图。
  • dims:计算出来的直方图的维数。
  • histSize:在每一维上直方图的个数。简单把直方图看作一个一个的竖条的话,就是每一维上竖条的个数。
  • ranges:用来进行统计的范围。比如 float rang1[] = {0, 20};float rang2[] = {30, 40}; const float*rangs[] = {rang1, rang2};那么就是对0,20和30,40范围的值进行统计。
  • uniform:每一个竖条的宽度是否相等。
  • accumulate: 是否累加。如果为true,在下次计算的时候不会首先清空hist。

画出直方图:

void line(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1,
         int lineType=8, int shift=0)
//两点确认一条直线。
//lineType:直线类型
//shift:坐标小数点维数
 
//画一个单一的实矩形
void rectangle(Mat& img, Point pt1,Point pt2, const Scalar& color, int thickness=1,
                 int lineType=8, int shift=0)
//一条对角线的两个顶点可确定一个矩形
//pt1和pt2互为对顶点
//thickness为负值表示矩形为实矩形
           

其中Point(x,y)表示二维坐标系下的点。

五、通道分离与合并通道

split用于通道分离

void split(const Mat& src,Mat *mvBegin)
           
第一个参数为要进行分离的图像矩阵,第二个参数是一个vector<Mat>对象
           

merge用于通道合并

void merge(const vector& mv, OutputArray dst );
           
第一个参数是图像矩阵向量容器,第二个参数是输出
           

举例:

std::vector<Mat> rgb(3);
 
split(src, rgb);              //分离通道
 for (int i = 0; i < 3; i++){
        rgb[i] = rgb[i].mul(show);
    }

merge(rgb, output);  //合并通道

           

六、寻找矩阵最小最大值

void minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
           

函数说明:

src:输入图像。
minVal:最小值,可輸入NULL表示不需要。
maxVal :最大值,可輸入NULL表示不需要。
minLoc:最小值的位置,可输入NULL表示不需要,Point类型。
maxLoc:最大值的位置,可输入NULL表示不需要,Point类型。
mask:可有可无的掩模。
           

七、绘制矩形

void rectangle(Mat& img, Point pt1,Point pt2,const Scalar& color, int thickness=1, int lineType=8, int shift=0)
           
img:输入图像.
pt1:矩形的一个顶点。
pt2:矩形对角线上的另一个顶点
color:线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image)。
thickness:组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。
line_type:线条的类型。
shift:坐标点的小数点位数。