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