1.cv::Mat有若干成員函數可以獲取圖像屬性,at(int y,int x)可以用來存取圖像元素,但是必須知道圖像數據類型!
例:
image.at<cv::Veb3b>(j,i)[channel]=value;//彩色圖像,其中channel注明了顏色通道號;```
類似的,open cv 還有二元,四元向量;
```cv::Mat_<uchar>im2=image;
im2(50,100)=0;//存取第50行,100列//重載了運算符()```
##2.使用指針遍歷圖像(使用雙重循環遍歷所有的像素值)
顏色縮減函數:
void colorReduce(cv::Mat&image,int div=64)
{
int n1=image.rows;//行數
int nc=image.cols*image.channels();//每行的元素個數
for(int j=0;j<n1;j++)//得到第j行的首地址
{
uchar* data=image.ptr<uchar>(j);//ptr可以得到任意行的首地址,此處返回第j行的首地址
for(int i=0;i<nc;i++)
{
//處理每一個像素
data[i]=data[i]/div*div+div/2
}//像素處理完成
}//行處理完成
}```
主函數:
image=cv::imread("boldt.jpg");
//處理圖像(調用函數)
colorReduce(image);
//顯示圖像
cv::namedWindow("image");
cv::imshow("image",image);```
#3.使用迭代器遍歷彩色圖像
void colorReduce(cv::Mat &image,int div=64)
{
cv::Mat_<cv::Vec3b>::iterator it=image.begin<cv::Vec3b>();//得到起始位置的迭代器
cv::Mat_<cv::Veb3b>::iterator itend=image.end<cv::Veb3b>();//得到終止位置的迭代器
for(;it!=itend;++it)
{//處理每個像素
(*)it[0]=(*)it[0]/div*div+div/2;
(*)it[1]=(*)it[1]/div*div+div/2;
(*)it[2]=(*)it[2]/div*div+div/2;
}
} ```
4.使用卷積核進行濾波,編寫圖像銳化函數
void sharpen2D(const cv::Mat &image,cv::Mat &result)
{
cv::Mat kernel(3,3,CV_32f,cv::Scalar(0));//構造核,所有的項初始化為0
//對核元素賦值
kernel.at<float>(1,1)=5.0;
kernel.at<float>(1,0)=-1.0;
kernel.at<float>(1,2)=-1.0;
kernel.at<float>(0,1)=-1.0;
kernel.at<float>(2,1)=-1.0;
//對圖像進行濾波
cv::filter2D(image,result,image.depth(),kernel);
}```
#5.進行簡單的圖像運算(此處僅針對兩個輸入圖像具有相同尺寸)
(1)加、減、乘、除
cv::add(image1,w1,image2,w2,b,result) ——> open cv2 里面對運算符進行了重載,可以直接寫符號: result=0.7image1+0.9image2
cv::substract 、cv::absdiff、cv::multiply、cv::divide```
(2)位運算符
cv::bitwise_and、cv::bitwise_or 、cv::bitwise_xor 、cv::bitwise_not
(3)找矩陣最大最小值、矩陣的一些運算
cv::max、 cv::min、矩陣求逆m1.inv()、矩陣轉置m1.t()、矩陣的行列式m1.determinate()、向量模v1.norm()、向量叉乘v1.cross(v2)、向量點乘v1.cross(v2)
(4)只接受一個輸入的操作符
cv::sqrt、 cv::pow 、cv::abs 、cv::cuberoot 、cv::exp 、cv::log
6.對圖像的一個通道進行操作后,再合并
//創建一個圖像向量
std::vector<cv::Mat>planes;
//將一個三通道圖像分離成三個單通道圖像
cv::spirit(image,planes);```
//將新圖層疊加到藍色通道
planes[0]+=image2;
//將三個單通道圖像合并為一個三通道圖像
cv::merge(planes,result);```
7.定義感興趣區域ROI(此處針對兩張圖像具有不同大小尺寸,比如想在原圖像上加一個logo)
只要ROI大小和logo圖片大小一致,則可以調用cv::add;ROI位置決定了logo圖像被插入的位置;
//定義圖像ROI
cv::Mat imageROI;//ROI與他的父圖像指向同一塊內存緩沖區
imageROI=image(cv::Rect(385,270,logo.cols,logo.rows))或者imageROI=image(cv::Range(270,270+logo.rows),cv::Range(385,385+logo.cols))
//插入logo 或 //加載掩模(必須是灰度圖)
cv::addWeighted(imageROI,1.0,logo,0.3,0.,imageROI) cv::Mat mask=cv::imread("logo.bmp",0) //此處0代表灰度圖像
//通過掩模拷貝ROI
logo.copyTo(imageROI,mask)```
8.類的設計
class ColorDetector{
private:
int minDist; //最小可接受距離
cv::Vec3b target;//目標色
cv::Mat result;//結果圖像
//構造函數
ColorDetector():minDist(100){
target[0]=target[1]=target[2]=0; //初始化默認參數
}
//設置顏色距離閾值,閾值必須是正,否則設為0
void setColorDistanceThreshold(int distance){
if(distance<0) distance=0;
minDist=distance;
}
//獲取顏色距離閾值
int getColorDistanceThreshold() const{
return minDist;
}
//設置需檢測的顏色
void setTargetColor(unsigned char blue,unsigned char green,unsigned char red){
target[0]=blue; arget[1]=green; target[2]=red;
}
//獲取需檢測的顏色
cv::Vec3b getTargetColor() const{
return target;
}
cv::Mat ColorDetctor::process(const cv::Mat &image){
result.create(image.rows,image.cols,CV_8U);//按需重新分配二值圖像,與輸入圖像的尺寸相同,但只有一個通道
//得到迭代器
cv::Mat_<cv::Vec3b>::const_iterator it=image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::const_iterator itend=image.end<cv::Vec3b>();
cv::Mat_<unchar>::iterator itout=result.begin<unchar>();
//遍歷每個像素
for(;it!=itend;++it,++itout){
if(getDistance(*it)<minDist) *itout=255;
else *itout=0;
}
return result;
}
//計算與目標顏色的距離
int getDistance(const cv::Vec3b& color)const{
return abs(color[0]-target[0])+abs(color[1]-target[1])+abs(color[2]-target[2]);
}
}
int main(){
//1.創建圖像處理對象
ColorDetector cdetect;
//2.讀取輸入圖像
cv::Mat image=cv::imread("1.jpg");
if(!image.data)
return 0;
//3.設置輸入參數
cdetect.setTargetColor(130,190,230);//藍天的顏色
cv::namedwindow("result");
//4.處理并顯示結果
cv::imshow("result",cdetect.process(image))
cv::waitkey();
return 0;
}```
9.控制器實現類之間的通信