天天看點

六、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:坐标點的小數點位數。