It's OpenCV
OpenCV的全稱是Open Source Computer Vision Library,是一個跨平臺的計算機視覺庫。
OpenCV可用于開發(fā)實時的圖像處理、計算機視覺以及模式識別程序,且授權(quán)可以在商業(yè)和研究領域中免費使用。
OpenCV用C++語言編寫,它的主要接口也是C++語言,但是依然保留了大量的C語言接口。該庫也有大量的Python,?Java?andMATLAB/OCTAVE的接口。
優(yōu)點顯而易見,而OpenCV目前最大的缺點就是,不能處理透明通道類似Png。
?
OpenCV第一步,顯示一張圖片
opencv中常見的與圖像操作有關的數(shù)據(jù)容器有Mat,cvMat和IplImage,這三種類型都可以代表和顯示圖像,
Mat類型側(cè)重于計算,數(shù)學性較高,openCV對Mat類型的計算也進行了優(yōu)化
而CvMat和IplImage類型更側(cè)重于“圖像”,opencv對其中的圖像操作(縮放、單通道提取、圖像閾值操作等)進行了優(yōu)化。
下面先采用Mat來記錄圖片。
算術運算:cv::add(), cv::addWeighted(), cv::scaleAdd(); cv::subtract, cv::absdiff; cv::multiply; cv::divide, 還可以通過mask參數(shù)來掩模不需要處理的位。
位運算:cv::bitwise_and, cv::bitwise_or, cv::bitwise_xor, cv::bitwise_not
其他運算:cv::sqrt, cv::pow, cv::abs, cv::cuberoot, cv::exp, cv::log
inv()求逆、t()求轉(zhuǎn)置、determinant()求行列式、norm()求矢量長度、cross()求兩個向量的叉乘、dot()求兩個向量的點乘。
#include "highgui.h" using namespace cv; int main() { char* imagename = "C:\\Users\\PCforSONG\\Desktop\\test.jpg";//Mat img = imread(imagename);Mat img(240,320,CV_8U,Scalar(100)); //大小是320*240,圖像上每個點的數(shù)據(jù)類型是無符號8位的,并用100填充所有像素點if(img.empty())return -1; //是否加載成功if(!img.data)return -1;namedWindow("圖片", CV_WINDOW_AUTOSIZE);imshow("圖片", img);Mat new_img=img.clone(); //創(chuàng)建一個副本 Mat newImage;newImage.create(new_img.size(),new_img.type()); //創(chuàng)建一個跟原圖像大小相同的圖像 imwrite(imagename,newImage);waitKey(5000);return 0; }?
newImage.create(new_img.size(),new_img.type()) ||?result.create(image.rows,image.cols,image.type())
new_img.type():
? CV_8U - 8-bit unsigned integers ( 0..255 )
? CV_8S - 8-bit signed integers ( -128..127 )
? CV_16U - 16-bit unsigned integers ( 0..65535 )
? CV_16S - 16-bit signed integers ( -32768..32767 )
? CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
? CV_32F - 32-bit ?oating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
? CV_64F - 64-bit ?oating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
?
?
使用另一種圖片處理類型 IplImage?
?cvResize就可以將源圖片轉(zhuǎn)成新圖片的大小
#include <cv.h> #include <highgui.h> #include <cmath>int main() {float scale = 0.3; //縮放倍數(shù)為0.618倍 CvSize dst_cvsize; //目標圖像尺寸 IplImage *src = cvLoadImage("C:\\Users\\PCforSONG\\Desktop\\Test2.jpg");dst_cvsize.width = src->width * scale; //目標圖像的寬為源圖象寬的scale倍 dst_cvsize.height = src->height * scale; //目標圖像的高為源圖象高的scale倍 IplImage *dst = cvCreateImage( dst_cvsize, src->depth, src->nChannels); //構(gòu)造目標圖象 cvResize(src, dst, CV_INTER_LINEAR); //縮放源圖像到目標圖像cvSaveImage("C:\\Users\\PCforSONG\\Desktop\\Test3.jpg", dst);cvNamedWindow( "src", CV_WINDOW_AUTOSIZE );cvNamedWindow( "dst", CV_WINDOW_AUTOSIZE );cvShowImage( "src", src ); //顯示源圖像cvShowImage( "dst", dst ); //顯示目標圖像cvWaitKey(-1);return 0; }?
?
第二步,圖像降色
圖像遍歷方法
image.at<uchar>(i,j):取出灰度圖像中i行j列的點。
image.at<Vec3b>(i,j)[k]:取出彩色圖像中i行j列第k通道的顏色點
image.ptr<uchar>(image.rows): 每行數(shù)據(jù)的指針,每行有個地址 image.cols*image.channels()
MatIterator_<Vec3b> it_out=outImage.begin<Vec3b>(),?itend_out=outImage.end<Vec3b>(): 迭代器訪問每個點
?
#include "highgui.h" using namespace cv;void colorReduce(Mat& image,int div) { //將每個通道的256種顏色用div種代替,每個顏色段取中間的顏色值作為代表色for(int i=0;i<image.rows;i++) {for(int j=0;j<image.cols;j++) {//image.at<Vec3b>(i,j)[k]:取出彩色圖像中i行j列第k通道的顏色點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;}} } int main() { char* imagename = "C:\\Users\\PCforSONG\\Desktop\\test.jpg";Mat img = imread(imagename);if(img.empty())return -1; //是否加載成功if(!img.data)return -1;namedWindow("圖片", CV_WINDOW_AUTOSIZE);//imshow("圖片", img);colorReduce(img, 64);imshow("圖片", img);waitKey(5000);return 0; }?
OpenCV中默認的像素點Vec3b由BRG?uchar數(shù)組[3]表示
降色至64色結(jié)果:
?
使用另一種圖片類型IplImage?
cvResize就可以實現(xiàn)對圖片的壓縮
#include <cv.h> #include <highgui.h> #include <cmath>int main() {float scale = 0.3; //縮放倍數(shù)為0.618倍 CvSize dst_cvsize; //目標圖像尺寸 IplImage *src = cvLoadImage("C:\\Users\\PCforSONG\\Desktop\\Test2.jpg"); //載入工作目錄下文件名為“tiger.jpg”的圖片。dst_cvsize.width = src->width * scale; //目標圖像的寬為源圖象寬的scale倍 dst_cvsize.height = src->height * scale; //目標圖像的高為源圖象高的scale倍 IplImage *dst = cvCreateImage( dst_cvsize, src->depth, src->nChannels); //構(gòu)造目標圖象 cvResize(src, dst, CV_INTER_LINEAR); //縮放源圖像到目標圖像cvSaveImage("C:\\Users\\PCforSONG\\Desktop\\Test3.jpg", dst);cvNamedWindow( "src", CV_WINDOW_AUTOSIZE );cvNamedWindow( "dst", CV_WINDOW_AUTOSIZE );cvShowImage( "src", src ); //顯示源圖像cvShowImage( "dst", dst ); //顯示目標圖像cvWaitKey(-1); //等待用戶響應return 0; }?
?
OpenCV第三步,臨域操作圖像銳化
#include "highgui.h" using namespace cv;void ImgFilter2d(const Mat &image,Mat& result) {result.create(image.size(),image.type());int nr=image.rows;int nc=image.cols*image.channels();//濾波算子為[0 –1 0;-1 5 –1;0 –1 0]//核心公式即:sharp(i.j)=5*image(i,j)-image(i-1,j)-image(i+1,j)for(int i=1;i<nr-1;i++) {const uchar* up_line=image.ptr<uchar>(i-1);//指向上一行const uchar* mid_line=image.ptr<uchar>(i);//當前行const uchar* down_line=image.ptr<uchar>(i+1);//下一行uchar* cur_line=result.ptr<uchar>(i);for(int j=1;j<nc-1;j++) {cur_line[j]=saturate_cast<uchar>(5*mid_line[j]-mid_line[j-1]-mid_line[j+1]-up_line[j]-down_line[j]);}}// 把圖像邊緣像素設置為0result.row(0).setTo(Scalar(0));result.row(result.rows-1).setTo(Scalar(0));result.col(0).setTo(Scalar(0));result.col(result.cols-1).setTo(Scalar(0)); } int main() { char* imagename = "C:\\Users\\PCforSONG\\Desktop\\test.jpg";Mat img = imread(imagename);if(img.empty())return -1; //是否加載成功if(!img.data)return -1;Mat ans;ImgFilter2d(img, ans);imshow("圖片", ans);waitKey(5000);return 0; }?
?
OpenCV第四步,PS的魔棒功能
cvtColor(A,B,CV_BGR2Lab); 將A顏色模式轉(zhuǎn)為CV_BGR2Lab存入B
cvtColor(Image,Image,CV_BGR2GRAY); 轉(zhuǎn)為灰度圖
#include "highgui.h" #include "cv.h" using namespace cv;class colorDetect { private:int minDist; //閥值Vec3b target; //目標顏色 public:Mat result;colorDetect() {};void SetMinDistance(int dist) {minDist = dist;};void SetTargetColor(uchar red,uchar green,uchar blue) {target[0] = blue, target[1] = red, target[2] = green;};void SetTargetColor(Vec3b color);Mat process(const Mat& image); }; Mat colorDetect::process(const Mat& image) {Mat ImageLab=image.clone();result.create(image.rows,image.cols,CV_8U);cvtColor(image,ImageLab,CV_BGR2Lab); //將image轉(zhuǎn)換為Lab格式存儲在ImageLab中Mat temp(1,1,CV_8UC3); //創(chuàng)建一張1*1的臨時圖像temp.at<Vec3b>(0,0)=target; //目標顏色填充cvtColor(temp,temp,CV_BGR2Lab); //將由默認的BGR轉(zhuǎn)換為Labtarget=temp.at<Vec3b>(0,0); //再從臨時圖像的Lab格式中取出Lab格式的目標顏色// 創(chuàng)建處理用的迭代器Mat_<Vec3b>::iterator it=ImageLab.begin<Vec3b>();Mat_<uchar>::iterator itout=result.begin<uchar>();while(it!=ImageLab.end<Vec3b>()) {//兩個顏色值之間距離的計算int dist=static_cast<int>(norm<int,3>(Vec3i((*it)[0]-target[0],(*it)[1]-target[1],(*it)[2]-target[2])));if(dist<minDist)(*itout)=255;else(*itout)=0;it++;itout++;}return result; } int main() { char* imagename = "C:\\Users\\PCforSONG\\Desktop\\test.jpg";Mat img = imread(imagename);if(img.empty())return -1; //是否加載成功if(!img.data)return -1;colorDetect OP;OP.SetMinDistance(80);OP.SetTargetColor(0, 255, 0);OP.process(img);imshow("圖片", OP.result);waitKey(50000);return 0; }?
1,在將圖像轉(zhuǎn)換為Lab空間,cvtColor(Old,New,type),將Old轉(zhuǎn)換為type格式(見第一步type())存儲在New中。
2,判斷兩個顏色之間的距離運算了norm函數(shù)求向量長度,它的運算是norm<typename,dim>(v)。其中v是一個dim維的向量。
下面為對實例圖片提取紅色的結(jié)果:
?
OpenCV第五步,直方圖和直方圖變換
圖像直方圖可以反映出圖像對比度,明暗程度等特征,所以我們可以利用直方圖的變換進行圖像畫面的調(diào)節(jié)。
OpenCV中計算圖像直方圖像函數(shù)是calcHist,它的參數(shù)比較多,下面分析一下它的接口和用法。
void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )const Mat* images:為輸入圖像的指針。int nimages:要計算直方圖的圖像的個數(shù)。此函數(shù)可以為多圖像求直方圖,我們通常情況下都只作用于單一圖像,所以通常nimages=1。const int* channels:圖像的通道,它是一個數(shù)組,如果是灰度圖像則channels[1]={0};如果是彩色圖像則channels[3]={0,1,2};如果是只是求彩色圖像第2個通道的直方圖,則channels[1]={1};IuputArray mask:是一個遮罩圖像用于確定哪些點參與計算,實際應用中是個很好的參數(shù),默認情況我們都設置為一個空圖像,即:Mat()。OutArray hist:計算得到的直方圖int dims:得到的直方圖的維數(shù),灰度圖像為1維,彩色圖像為3維。const int* histSize:直方圖橫坐標的區(qū)間數(shù)。如果是10,則它會橫坐標分為10份,然后統(tǒng)計每個區(qū)間的像素點總和。const float** ranges:這是一個二維數(shù)組,用來指出每個區(qū)間的范圍。?
實例代碼
#include "cv.h" #include "highgui.h" #include <cstdio> using namespace cv;Mat getHistImg(const MatND& hist) {double maxVal=0;double minVal=0;//找到直方圖中的最大值和最小值minMaxLoc(hist,&minVal,&maxVal,0,0);int histSize=hist.rows;Mat histImg(histSize,histSize,CV_8U,Scalar(255));// 設置最大峰值為圖像高度的90%int hpt=static_cast<int>(0.9*histSize);for(int h=0;h<histSize;h++) {float binVal=hist.at<float>(h);int intensity=static_cast<int>(binVal*hpt/maxVal);line(histImg,Point(h,histSize),Point(h,histSize-intensity),Scalar::all(0));}imshow("直方圖", histImg);//找到直方圖最大最小值對應的灰度值int imax,imin;for(imin=0;imin<256;imin++)if(hist.at<float>(imin)==minVal)break;for(imax=255;imax>=0;imax--)if(hist.at<float>(imax)==maxVal)break;//創(chuàng)建灰度變換表Mat lut(1,256,CV_8U);for(int i=0;i<256;i++) {if(lut.at<uchar>(i)<imin)lut.at<uchar>(i)=imin;else if(lut.at<uchar>(i)>imax)lut.at<uchar>(i)=imax;elselut.at<uchar>(i)=static_cast<uchar>(255.0*(i-imin)/(imax-imin)+0.5);}return lut; }int main() {Mat Image=imread("C:\\Users\\PCforSONG\\Desktop\\test.jpg");cvtColor(Image,Image,CV_BGR2GRAY); //轉(zhuǎn)為灰度圖//imshow("圖片", Image);const int channels[1]={0};//如果是灰度圖像則channels[1]={0};如果是彩色圖像則channels[3]={0,1,2};如果是只是求彩色圖像第2個通道的直方圖,則channels[1]={1}const int histSize[1]={256};float hranges[2]={0,255};const float* ranges[1]={hranges};MatND hist;calcHist(&Image,1,channels,Mat(),hist,1,histSize,ranges);//calcHist(輸入圖像指針, 幾圖像求直方圖, 通道, 遮罩, 得到的直方圖,直方圖的維數(shù)灰1彩3, 橫坐標的區(qū)間數(shù), 區(qū)間的范圍) Mat result;LUT(Image,getHistImg(hist),result);//通過得到的lut灰度替換表,讓灰度平均分布,對比度增強imshow("直方圖變換", result);waitKey(5000);return 0; }?
?
OpenCV第六步,鼠標繪圖函數(shù)
這一次使用IplImage結(jié)構(gòu)來存儲圖片。
cvSetMouseCallback("鼠標繪圖", func, (void*)img); 返回某窗口的鼠標事件傳參給func函數(shù),最后一個參數(shù)為用戶自己定義,本例需傳遞圖片指針
void func(int event, int x, int y, int extra_event, void* img) 鼠標消息傳入函數(shù)參數(shù),第一個參數(shù)為鼠標事件(按下,移動,松開),第二三個為鼠標坐標,第四個為附加事件。
#include "cv.h" #include "highgui.h" using namespace std;void func(int event, int x, int y, int extra_event, void* img) { //鼠標消息傳入函數(shù)參數(shù)static bool MouseLButtonDown = 0;static CvPoint from = cvPoint(0, 0);switch (event) {case CV_EVENT_LBUTTONDOWN:MouseLButtonDown = 1;from = cvPoint(x, y);break;case CV_EVENT_LBUTTONUP:MouseLButtonDown = 0;break;case CV_EVENT_MOUSEMOVE:if (MouseLButtonDown) {CvPoint to = cvPoint(x, y);cvLine((IplImage*)img, from, to, CV_RGB(0, 0, 0), 2); //在img上兩點繪制粗為2的直線from = to;cvShowImage("鼠標繪圖", (IplImage*)img);}break;} } int main() {IplImage *img = cvCreateImage(cvSize(1080, 768), IPL_DEPTH_8U, 3);cvSet(img, CV_RGB(255, 255, 255)); //用cvSet()將圖像填充成白色cvNamedWindow("鼠標繪圖", CV_WINDOW_AUTOSIZE); //創(chuàng)建名字為的窗口cvShowImage("鼠標繪圖", img); //在指定名字的窗口顯示圖片 cvSetMouseCallback("鼠標繪圖", func, (void*)img);do {int key = cvWaitKey(0);switch (key) {case 'r':cvSet(img, CV_RGB(255, 255, 255));cvShowImage("鼠標繪圖", img);break;case 's':cvSaveImage("已繪圖片.jpg", img);break;}}while (1);cvDestroyWindow("鼠標繪圖");cvReleaseImage(&img);return 0; }?
為大家鼠標繪制了一張圖片,12月 25日圣誕快樂!
?
?
OpenCV第七步,Sobel算子的邊緣檢測
canny邊緣檢測函數(shù)
cvCanny(SrcImage, CannyImg, threshold, threshold * 3, 3)
輸入圖像(單通道灰度圖)+輸出邊緣圖像(單通道黑白圖)+[像素的梯度大與上限值則是邊緣像素 || 小于下限值則被拋棄 ||?在兩者之間則當這個點與高于上限值的像素點連接時保留,否則刪除]+Sobel 算子階數(shù)
threshold(result,result,40,255,THRESH_BINARY); 用來對灰度圖進行二值化,THRESH_BINARY時像素值大于40的都設為255.
#include "cv.h" #include "highgui.h" using namespace cv;IplImage *SrcImage, *CannyImg;void func(int threshold) { //cvCreateTrackbar的回調(diào)函數(shù)cvCanny(SrcImage, CannyImg, threshold, threshold * 3, 3); //canny邊緣檢測//輸入圖像(單通道灰度圖)+輸出邊緣圖像(單通道黑白圖)+像素的梯度大與上限值則是邊緣像素/小于下限值則被拋棄// 在兩者之間則當這個點與高于上限值的像素點連接時保留,否則刪除+Sobel 算子階數(shù)cvShowImage("邊緣檢測圖", CannyImg); } int main() {const char *pstrImageName = "C:\\Users\\PCforSONG\\Desktop\\test.jpg";//從文件中載入圖像的灰度圖CV_LOAD_IMAGE_GRAYSCALESrcImage = cvLoadImage(pstrImageName, CV_LOAD_IMAGE_GRAYSCALE);CannyImg = cvCreateImage(cvGetSize(SrcImage), IPL_DEPTH_8U, 1);cvNamedWindow("邊緣檢測圖", CV_WINDOW_AUTOSIZE);func(40);//創(chuàng)建trackbar并添加到指定窗口,名字+窗口名字+滑塊位置+滑塊最大值+回調(diào)函數(shù),默認顯示在窗口頂int nThresholdEdge = 40;cvCreateTrackbar("Threshold", "邊緣檢測圖", &nThresholdEdge, 100, func);cvWaitKey(0);cvDestroyWindow("邊緣檢測圖");cvReleaseImage(&SrcImage);cvReleaseImage(&CannyImg);return 0; }?
檢測完邊緣,當然還可以繼續(xù)對邊緣進行檢測,如檢測直線,HoughLinesP()
它的輸入是一個二值的輪廓圖像,即邊緣檢測得到的圖像;它的輸出是一個Vector of Vec4i,數(shù)組中的每個元素是一個4元浮點極坐標<rou,theta>,rou代表直線離坐標原點的距離,theta代表角度,前兩個一組,后兩個一組,表示一條直線的起點和終點的極坐標。第3和第4個參數(shù)代表步長,因為Hough變換是窮舉的算法,rho表示距離的步長,theta代表角度的步長。第5個參數(shù)是一個閾值設置直接的最低投票個數(shù)。
vector<Vec4i> lines; // 檢測直線,最小投票為90,線條不短于50,間隙不小于10 HoughLinesP(contours,lines,1,CV_PI/180,80,50,10); vector<Vec4i>::const_iterator it=lines.begin(); while(it!=lines.end()) {Point pt1((*it)[0],(*it)[1]);Point pt2((*it)[2],(*it)[3]);line(image,pt1,pt2,color,2);it++; }?
?
OpenCV第八步,利用直方圖進行圖像相似度檢測
圖像相似性比較是比上面直方圖映射更加實用且普通的例子,前段時間淘寶或百度推出類似搜圖的功能都離不開圖像相似性判斷這個話題,當然本文這里面不可能去深入探討些解決方案的實現(xiàn),只是利用OpenCV中的例程來簡單的實現(xiàn)圖片的匹配。?
圖片需要先降維,再求出圖片的直方圖。
直方圖的比較函數(shù)為compareHist(AImg,BImg,CV_COMP_BHATTACHARYYA),最后一個參數(shù)是兩個直方圖間距離計算的方法。
#include "cv.h" #include "highgui.h" #include <iostream> using namespace cv;void colorReduce(Mat& image,int div) { //將每個通道的256種顏色用div種代替,每個顏色段取中間的顏色值作為代表色for(int i=0;i<image.rows;i++) {for(int j=0;j<image.cols;j++) {//image.at<Vec3b>(i,j)[k]:取出彩色圖像中i行j列第k通道的顏色點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;}} }Mat getHistImg(const Mat& hist) {const int channels[1]={0};const int histSize[1]={256};float hranges[2]={0,255};const float* ranges[1]={hranges};MatND histImg;calcHist(&hist,1,channels,Mat(),histImg,1,histSize,ranges);return histImg; }int main() {Mat refImg=imread("ref.png");imshow("zz", refImg);Mat image1=imread("image1.png");Mat image2=imread("image2.png");//圖像顏色降至64colorReduce(refImg,64);colorReduce(image1,64);colorReduce(image2,64);MatND refH=getHistImg(refImg);MatND hist1=getHistImg(image1);MatND hist2=getHistImg(image2);double dist1,dist2;dist1=compareHist(refH,hist1,CV_COMP_BHATTACHARYYA);dist2=compareHist(refH,hist2,CV_COMP_BHATTACHARYYA);printf("%.4lf %.4lf\n", dist1, dist2);return 0; }?
OpenCV第九步,形態(tài)學操作函數(shù)
形態(tài)學實際上可以理解為一種濾波行為,所以很多地方稱它為形態(tài)學濾波。我們?yōu)V波中用的濾波器(kernel)在這里被稱為結(jié)構(gòu)元素,結(jié)構(gòu)元素往往是由一個特殊的形狀構(gòu)成,如:線條、矩形、圓、菱形等。我們把結(jié)構(gòu)元素的中心(Anchor Point)與圖像上像素點對齊,然后結(jié)構(gòu)元素覆蓋的領域像素就是我們要分析的像素,我們定義一種操作就形成了一種形態(tài)學運算。
#include "cv.h" #include "highgui.h" #include <iostream> using namespace cv;int main() {Mat image=imread("C:\\Users\\PCforSONG\\Desktop\\test2.jpg");cvtColor(image,image,CV_BGR2GRAY); //彩色轉(zhuǎn)灰度 Mat Img;morphologyEx(image,Img,MORPH_GRADIENT,Mat());//原理,對圖像先做了一個腐蝕,再做了一次膨脹,然后將兩次的結(jié)果相減threshold(Img,Img,40,255,THRESH_BINARY); //二值化namedWindow("Img");imshow("Img",Img);waitKey();return 0; }?
下面實現(xiàn)用形態(tài)學操作來檢測角點
#include "cv.h" #include "highgui.h" #include <iostream> using namespace cv;int main() {Mat image=imread("C:\\Users\\PCforSONG\\Desktop\\test2.jpg");cvtColor(image,image,CV_BGR2GRAY); //轉(zhuǎn)灰度圖//定義結(jié)構(gòu)元素,十字/菱形/正方形/X形Mat cross(5,5,CV_8U,Scalar(0));Mat diamond(5,5,CV_8U,Scalar(1));Mat square(5,5,CV_8U,Scalar(1));Mat x(5,5,CV_8U,Scalar(0));for(int i=0;i<5;i++) {cross.at<uchar>(3,i)=1;cross.at<uchar>(i,3)=1;}diamond.at<uchar>(0,0)=0;diamond.at<uchar>(0,1)=0;diamond.at<uchar>(1,0)=0;diamond.at<uchar>(4,4)=0;diamond.at<uchar>(3,4)=0;diamond.at<uchar>(4,3)=0;diamond.at<uchar>(4,0)=0;diamond.at<uchar>(4,1)=0;diamond.at<uchar>(3,0)=0;diamond.at<uchar>(0,4)=0;diamond.at<uchar>(0,3)=0;diamond.at<uchar>(1,4)=0;for(int i=0;i<5;i++){x.at<uchar>(i,i)=1;x.at<uchar>(4-i,i)=1;}Mat result;dilate(image,result,cross);erode(result,result,diamond);Mat result2;dilate(image,result2,x);erode(result2,result2,square);absdiff(result2,result,result);//二值化threshold(result,result,40,255,THRESH_BINARY);for(int i=0;i<result.rows;i++) {const uchar* data=result.ptr<uchar>(i);for(int j=0;j<result.cols;j++) {if(data[j] > 0) //角點圖像上的白點circle(image,Point(j,i),8,Scalar(255,255,255));// 畫圈 }}imshow("Img", image);waitKey();return 0; }?
OpenCV第十步,濾波器
濾波實際上是信號處理里的一個概念,其中像素點灰度值的高低代表信號的強弱。
高頻:圖像中灰度變化劇烈的點。
低頻:圖像中平坦的,灰度變化不大的點。
根據(jù)圖像的高頻與低頻的特征,我們可以設計相應的高通與低通濾波器,
高通濾波可以檢測圖像中尖銳、變化明顯的地方;低通濾波可以讓圖像變得光滑,濾除圖像中的噪聲。
一、線性濾波器:鄰域內(nèi)的像素按照一個權(quán)重相加最后設置為當前點的灰度值(卷積)
1,blur函數(shù):用一個點鄰域內(nèi)像素的平均灰度值來代替該點的灰度
blur(image,result,cv::Size(5,5));
2,高斯模糊
平均值來代替當前的灰度值,且越靠近該像素的點提供越高的權(quán)重,這樣就產(chǎn)生了高斯模糊濾波。它的濾波器或者叫遮罩是一個高斯分布的二維矩陣。?
GaussianBlur(image,result,cv::Size(5,5),1.5);
參數(shù)image為輸入圖像,result為輸出圖像,Size(5,5)定義了核的大小,最后一個參數(shù)說明了高斯核的方差。
?
二、非線性濾波器:
3,中值濾波:它是取鄰域內(nèi)所有像素的中位數(shù)作為當前點的灰度值。
medianBlur(image,result,5);
其中最后一個參數(shù)指定了鄰域的大小為5*5。中值濾波也是在實際中應用最多的平滑濾波。
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/updateofsimon/p/3482732.html
總結(jié)
以上是生活随笔為你收集整理的It's OpenCV的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 想去华为学习人力资源管理怎么报名
- 下一篇: 怎么快速高效的排课?