国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

opencv 入門學(xué)習(xí)筆記(C++)

這篇具有很好參考價(jià)值的文章主要介紹了opencv 入門學(xué)習(xí)筆記(C++)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

opencv 入門學(xué)習(xí)筆記(C++)

4.1.2 Mat 結(jié)構(gòu)的使用

? 關(guān)于Mat類,我們首先要知道的是:

(1)不必再手動(dòng)為其開辟空間。

(2)不必再在不需要時(shí)立即將空間釋放

總結(jié):

  • OpenCV 函數(shù)中輸出圖像的內(nèi)存分配是自動(dòng)完成的
  • 使用opencv的c++結(jié)構(gòu)時(shí)不需要考慮內(nèi)存釋放的問日
  • 賦值運(yùn)算符和拷貝構(gòu)造函數(shù) Mat B(A)只復(fù)制信息頭
  • 使用函數(shù) clone()或者 copyTo()來復(fù)制一副圖像的矩陣

4.1.3 像素值的存儲(chǔ)方法

  • RGB/RGBA
  • YCrCb在JPEG中廣泛使用
  • HSV和HLS 把顏色分解成色調(diào)、飽和度和亮度。

4.1.4 顯式創(chuàng)建Mat對(duì)象的七種方式

  • 【方法一】使用Mat()構(gòu)造函數(shù)

    Mat M(2,2,CV_8UC3,Scalar(0,0,255));
    //CV_[位數(shù)][帶符號(hào)與否][類型前綴]C[通道數(shù)]
    //預(yù)先定義的通道數(shù)可以多達(dá)4個(gè)
    
  • 【方法二】在C/C++中通過構(gòu)造函數(shù)進(jìn)行初始化

    int sz[3]={2,2,2};
    Mat L(3,sz,cv_8UC,Scalar::all(0));
    //上面的例子演示了如何創(chuàng)建一個(gè)超過兩維的矩陣:指定維數(shù),然后傳遞給一個(gè)指向數(shù)組的指針,這個(gè)數(shù)組包含每個(gè)維度的尺寸;后續(xù)兩個(gè)參數(shù)與方法一中的相同
    
  • 【方法三】為已存在的IplImage指針創(chuàng)建信息頭

    IplImage* img = cvLoadImage("1.jpg",1);
    Mat mtx(img);//轉(zhuǎn)換 IplImage*->Mat
    
  • 【方法四】利用Create()函數(shù)

    M.create(4,4,CV_8UC(2));
    //需要注意的是,此方法不能為矩陣設(shè)初值,只是在該百年尺寸時(shí)重新為矩陣數(shù)據(jù)開辟內(nèi)存而已。
    
  • 【方法六】對(duì)小矩陣使用逗號(hào)分隔式初始化函數(shù)

    Mat C = (Mat_<double>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
    cout<<"C = "<<endl<<" "<C<<endl<<endl;
    
  • 【方法七】為已存在的對(duì)象創(chuàng)建新信息頭

    Mat RowClone = C.row(1).clone();
    cout<<"RowClone = "<<endl<<" "<<RowClone<<endl<<endl;
    //方法七為使用成員函數(shù)clone()或者copyTo()為一個(gè)已存在的Mat對(duì)象創(chuàng)建一個(gè)新的信息頭
    

cvtColor

  • cvtColor的功能是把圖像從一個(gè)色彩空間轉(zhuǎn)換到另外一個(gè)色彩空間,有三個(gè)參數(shù),第一個(gè)參數(shù)表示源圖像,第二個(gè)參數(shù)表示色彩空間轉(zhuǎn)換之后的圖像,第三個(gè)參數(shù)表示源和目標(biāo)色彩空間如:COLOR_BGR2HLS、COLOR_BGR2GRAY等
  • cvtColor(image,gray_image,COLOR_BGR2GRAY);

imwrite

  • 保存文件到指定的目錄途徑
  • 只有8位,16位的PNG/JPG/Tiff文件格式而且是單通道或者三通道的BGR圖像 才可以通過這種方式保存
  • 保存PNG格式的時(shí)候可以保存透明通道的圖片(RGBA)
  • 可以指定壓縮參數(shù)

矩陣的掩碼操作

  • 獲取圖像像素指針

  • 掩碼操作解釋

  • 代碼演示

像素處理范圍 saturate_cast<uchar> 這個(gè)函數(shù)的功能是確保RGB值得范圍在0~255之間

掩碼操作實(shí)現(xiàn)圖像對(duì)比度的調(diào)整 I ( i , j ) = 5 ? I ( i , j ) ? [ I ( i ? 1 , j ) + I ( i + 1 , j ) + I ( i , j ? 1 ) , I ( i , j + 1 ) ] I(i,j)=5*I(i,j)-[I(i-1,j)+I(i+1,j)+I(i,j-1),I(i,j+1)] I(i,j)=5?I(i,j)?[I(i?1,j)+I(i+1,j)+I(i,j?1),I(i,j+1)]

#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
int main(int argc,char** argv)
{
	Mat src = imread("test.jpg");
	Mat dst;
	if (!src.data)//如果圖像為空,返回 error
	{
		std::cout << "can't load this img" <<std::endl;
		return -1;
	}
	namedWindow("input image", WINDOW_AUTOSIZE);
	imshow("input image", src);
//RGB圖像按列存儲(chǔ),注意存儲(chǔ)順序是BGR
	int cols = (src.cols - 1) * src.channels();
    //cols 應(yīng)該用width更為妥當(dāng),-1是因?yàn)橐粘鲆涣邢袼匾苑罒o定義
	int offsetx = src.channels();
    //偏移量是通道數(shù)
	int rows = src.rows;
    //RGB按照列存儲(chǔ),與行數(shù)無關(guān)
	dst = Mat::zeros(src.size(), src.type());
    //重新創(chuàng)建一個(gè)mat矩陣用于存放輸出的圖像
    //src.copyTo(dst);也可
	for (int row = 1; row < rows - 1; row++) {
		const uchar* previous = src.ptr<uchar>(row - 1);
		const uchar* current = src.ptr<uchar>(row);
		const uchar* next = src.ptr<uchar>(row +1);
        //創(chuàng)建核的數(shù)組
		uchar* output = dst.ptr<uchar>(row);
		for (int col = offsetx; col < cols; col++) {
			output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));
		}
	}
	namedWindow("constrast image", WINDOW_AUTOSIZE);
	imshow("constrast image", dst);
	waitKey(0);
	return 0;
}

opencv c++,opencv,學(xué)習(xí),筆記

函數(shù)filter 2D實(shí)現(xiàn)掩碼操作

可直接用opencv的API做掩碼操作來提高對(duì)比度

filter2D(src,dst,src.depth(),kernel):其中src與dst是Mat類型變量,src.depth表示位圖深度,有32、24、8等,直接寫-1表示與輸入圖深度一致。(filter濾波器)

定義掩碼: Mat lernel = (Mat_<char>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);

#include <opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
#include<stdlib.h>
using namespace cv;

int main(int argc, char** argv) {
	Mat src = imread("C:/Users/admin/Desktop/lenna.png");//讀入圖片
	Mat dst;//提高對(duì)比度之后的圖片矩陣
	if (src.empty()){ // 特判
		printf("cannot see\n");
		return -1;
	}
	namedWindow("opencv setup1", CV_WINDOW_AUTOSIZE);
	imshow("opencv setup1", src);
	Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//定義掩碼規(guī)則
	filter2D(src, dst, src.depth()/*-1*/, kernel);
	//輸出目標(biāo)圖像
	namedWindow("opencv setup2", CV_WINDOW_AUTOSIZE);
	imshow("opencv setup2", dst);
	waitKey(0);
	system("pause");   //以便在退出程序前調(diào)用系統(tǒng)的暫停命令暫停命令行
//爽得很??!
}

Mat

mat對(duì)象的使用:

  • 部分復(fù)制:一般情況下只會(huì)復(fù)制mat對(duì)象的頭和指針部分,不會(huì)復(fù)制數(shù)據(jù)部分
  • 完全復(fù)制:使用如下兩個(gè)API:
Mat F=A.clone();
//或者
Mat G;
A.copyTo(G);

函數(shù)用法:

#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc,char** argv)
{
	Mat src = imread("test.jpg");

	if (!src.data)
	{
		std::cout << "can't load this img" <<std::endl;
		return -1;
	}
	//namedWindow("input image", WINDOW_AUTOSIZE);
	//imshow("input image", src);
	/*Mat dst;
	dst = Mat(src.size(), src.type());
	dst = Scalar(255, 0, 255);
	namedWindow("out put", WINDOW_AUTOSIZE);
	imshow("out put", dst);*/


	/*Mat dst = src.clone();
	namedWindow("out put", WINDOW_AUTOSIZE);
	imshow("out put", dst);*/

	//Mat dst;
	//cvtColor(src, dst, COLOR_BGR2GRAY); 
	//namedWindow("out put", WINDOW_AUTOSIZE);
	//imshow("out put", dst);
	//cout << src.channels() << endl;//通道數(shù)目
	//cout << dst.channels() << endl;
	//int cols = dst.cols;//全部的列
	//int rows = dst.rows;//全部的行
	//const uchar* firstRow = dst.ptr<uchar>(0);
	//printf("%d", *firstRow);
	Mat M(3, 3, CV_8UC3, Scalar(0, 0, 255));
    
    Mat  m1;
    m1.create(src.size(),src.type());
    m1=Scalar(0,0,255);
    
    Mat m2 = Mat::zeros(src.size(),src.type()); 
      Mat m2 = Mat::zeros(2,2,CV_8UC1);
      Mat m2 = Mat::eye(2,2,CV_8UC1); 
    
	cout << M << endl;
	waitKey(0);
	return 0;
}

圖片操作

讀寫圖像

  • imread可以指定加載為灰度圖像或者RGB圖像
  • imwrite保存圖像文件,類型由擴(kuò)展名決定

讀寫像素(pixel)

  • 讀取一個(gè)GRAY像素點(diǎn)的像素值(CV_8UC1)

Scalar intensity = img.at<uchar>(y,x);或者

Scalar intensity = img.at<uchar>(Point(y,x));

  • 讀一個(gè)RGB像素點(diǎn)的像素值
Vec3f intensity = img.at<Vec3f>(y,x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];
  • 獲取像素的練習(xí)

    #include <opencv2/core/utils/logger.hpp>
    #include<opencv2/opencv.hpp>
    #include<iostream>
    using namespace cv;
    using namespace std;
    int main(int argc, char** argv)
    {
    	cv::utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);//不再輸出日志
    	Mat src = imread("test.jpg");
    	if (!src.data) {
    		cout << "could not load this image..." << endl;
    	}
    	char output_origin[] = "origin demo";
    	char output_gray[] = "gray demo";
    	namedWindow(output_origin, WINDOW_AUTOSIZE);
    	imshow(output_origin, src);
    	Mat dst;
    	cvtColor(src, dst, COLOR_BGR2GRAY);
    	namedWindow(output_gray, WINDOW_AUTOSIZE);
    	imshow(output_gray, dst);
    dst.create(src.size(), src.type());
    	for (int row = 0; row < dst.rows; row++)
    		for (int col = 0; col <dst.cols; col++) {
    			//int gray = dst.at<uchar>(row,col);
    			//dst.at<uchar>(row,col) = 255 - gray;
    			int b = src.at<Vec3b>(row, col)[0];
    			int g = src.at<Vec3b>(row, col)[1];
    			int r = src.at<Vec3b>(row, col)[2];
    			dst.at<Vec3b>(row, col)[0]=255-b;
    			dst.at<Vec3b>(row, col)[1] = 255 -g;
    			dst.at<Vec3b>(row, col)[2] = 255 - r;
                //另一種轉(zhuǎn)換成灰度圖像的方法:
                //dst.at<uchar>(row,col)=max(r,max(b,g));
                //dst.at<uchar>(row,col)=min(r,min(b,g));
    		}
    	namedWindow("anti color demo", WINDOW_AUTOSIZE);
    	imshow("anti color demo", dst);
    	waitKey(0);
    }
    //已經(jīng)有封裝好的API干嘛要練習(xí)這個(gè)
    bitwise_not(src,dst);
    

    Vec3b與Vec3f

  • Vec3b對(duì)應(yīng)的三通道的順序是blue、green、red的uchar類型的數(shù)據(jù)

  • Vec3f對(duì)應(yīng)三通道的float類型數(shù)據(jù)

  • 把CV_8UC1轉(zhuǎn)換到CV32F1實(shí)現(xiàn)如下: src.convertTo(dst,CV_32F);

圖像混合

理論-線性混合操作

g ( x ) = ( 1 ? α ) f 0 ( x ) + α f 1 ( x ) 其中 α 的取值范圍為 0 到 1 之間 g(x)=(1-\alpha)f_0(x)+\alpha f_1(x)\\其中\(zhòng)alpha的取值范圍為0到1之間 g(x)=(1?α)f0?(x)+αf1?(x)其中α的取值范圍為01之間

相關(guān)的API(addWeighted):

addWeight(src1,alpha,src2,beta,gamma(校驗(yàn)值),dst);

d s t ( I ) = s a t u r a t e _ c a s t ( s r c 1 ( I ) ? a l p h a + s r c 2 ( I ) ? b e t a + g a m m a ) dst(I)=saturate\_cast(src1(I)*alpha+src2(I)*beta+gamma) dst(I)=saturate_cast(src1(I)?alpha+src2(I)?beta+gamma)

改變圖像的亮度和對(duì)比度

理論:

  • 圖像變換可以看作如下:

    • 像素變換——點(diǎn)操作
    • 鄰域操作——區(qū)域

    調(diào)整圖像亮度屬于像素變換-點(diǎn)操作 g ( i , j ) = α f ( i , j ) + β g(i,j)=\alpha f(i,j)+\beta g(i,j)=αf(i,j)+β其中 α \alpha α>0, β \beta β是增益變量

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
	Mat src = imread("test.jpg");
	char input_win[] = "src image";
	if (!src.data) {
		cout << "could not load the image..." << endl;
	}
	namedWindow(input_win, WINDOW_AUTOSIZE);
	imshow(input_win, src);
	Mat dst;
	int height = src.rows;
	int width = src.cols;
	dst = Mat::zeros(src.size(), src.type());
	double alpha = 1.5;
	double beta = 10;
	src.convertTo(src, CV_32F);
	for (int row = 0; row < height; row++)
		for (int col = 0; col < width; col++) {
			if (src.channels()  3) {
				float b = src.at<Vec3f>(row, col)[0];
				float g = src.at<Vec3f>(row, col)[1];
				float r = src.at<Vec3f>(row, col)[2];
				dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b * alpha + beta);
				dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g * alpha + beta);
				dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r * alpha + beta);
			}
			else if (src.channels()  1) {
				int v = src.at<uchar>(row, col);
				dst.at<uchar>(row, col) = saturate_cast<uchar>(v * alpha + beta);
			}
			//else
		}
	char output_title[] = "contrast and brightness change demo";
	namedWindow(output_title, WINDOW_AUTOSIZE);
	imshow(output_title, dst);
	waitKey(0);
}

繪制圖像和文字

  • 使用Point與Scalar

    • ? Point表示2D平面上一個(gè)點(diǎn)(x,y)

      Point p;
      p.x=10;p.y=8;//p=Point(10,8);
      
    • Scalar表示四個(gè)元素的向量

      Scalar(a,b,c);//a=bule,b=green,c=red表示RGB三個(gè)通道
      
  • 在圖片中插入線、矩形、橢圓、圓、多邊形。

    #include<opencv2/opencv.hpp>
    #include<iostream>
    using namespace cv;
    using namespace std;
    Mat src;
    void lines();
    void myRectangle();
    void myEllipse();
    void myCircle();
    void myPolygon();
    int main(int argc, char** argv)
    {
    	 src = imread("test.jpg");
    	if (!src.data) {
    		cout << "could not liad this image.." << endl;
    		return -1;
    	}
    	lines();
    	myRectangle();
    	myEllipse();
    	myCircle();
    	myPolygon();
    	namedWindow("line_demo", WINDOW_AUTOSIZE);
    	imshow("line_demo", src);
    	waitKey(0);
    }
    void lines() {//線
    	Point p1 = Point(20, 30);
    	Point p2 = Point(200, 300);
    	Scalar color =Scalar(0, 0, 255);
    	line(src, p1, p2, color, 5, LINE_AA);
    }
    void myRectangle() {//矩形
    	Rect rect = Rect(200, 100, 300, 300);
    	Scalar color = Scalar(0, 0, 255);
    	rectangle(src, rect, color,1, LINE_8);
    }
    void myEllipse() {//橢圓
    	Scalar color = Scalar(175, 145, 76);
    	ellipse(src, Point(src.cols/ 2, src.rows / 2), Size(src.rows / 4, src.cols / 8), 0, 0, 360, color, 1, LINE_AA);
    }
    void myCircle() {//圓
    	Scalar color = Scalar(175, 146, 76);
    	circle(src, Point(src.cols / 2, src.rows / 2), src.cols / 4, color, 1, LINE_AA);
    }
    void myPolygon() {//多邊形
    	Scalar color = Scalar(0, 0, 255);
    	Point pts [1][6];
    	pts[0][0] = Point(100, 100);
    	pts[0][1] = Point(100, 200);
    	pts[0][2] = Point(200, 200);
    	pts[0][3] = Point(200, 100);
    	pts[0][4] = Point(150, 50);
    	pts[0][5] = Point(100, 100);
    	const Point* ppts[] = { pts[0] };
    	int npt[] = { 6 };
    	fillPoly(src, ppts, npt, 1, color, 8);
    }
    
  • 在圖像中插入文字。putText();

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
Mat src;

int main(int argc, char** argv)
{
	 src = imread("test.jpg");
	if (!src.data) {
		cout << "could not liad this image.." << endl;
		return -1;
	}
	putText(src, "hello opencv", Point(src.cols / 2-60, src.rows / 2), FONT_HERSHEY_COMPLEX, 0.8, Scalar(150, 12, 255), 1, 8);
	namedWindow("line_demo", WINDOW_AUTOSIZE);
	imshow("line_demo", src);
	waitKey(0);
}
//隨機(jī)生成顏色

  • 隨機(jī)生成線條

    #include<opencv2/opencv.hpp>
    #include<iostream>
    using namespace cv;
    using namespace std;
    Mat src;
    void RandowLineDemo();
    
    int main(int argc, char** argv)
    {
    	 src = imread("test.jpg");
    	if (!src.data) {
    		cout << "could not liad this image.." << endl;
    		return -1;
    	}
    	//putText(src, "hello opencv", Point(src.cols / 2-60, src.rows / 2), FONT_HERSHEY_COMPLEX, 0.8, Scalar(150, 12, 255), 1, 8);
    	RandowLineDemo();
    	//namedWindow("line_demo", WINDOW_AUTOSIZE);
    	//imshow("line_demo", src);
    	waitKey(0);
    }
    void RandowLineDemo() {
    	RNG rng(12346);//RNG 變量(種子數(shù))
    	Mat bg = Mat::zeros(src.size(), src.type());
    	for (int i = 0; i < 10000; i++) {
    		line(bg, Point(rng.uniform(0, src.cols), rng.uniform(0, src.rows)), Point(rng.uniform(0, src.cols), rng.uniform(0, src.rows)), Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 1, LINE_AA);
            //rng.uniform(范圍);
    		if (waitKey(50) > 0) {
    			break;
    	}
    		imshow("RandowLineDemo", bg);
    	}
    	}
    
    

模糊圖像

模糊原理

  • Smooth/Blur是圖像處理中最簡單和常用的操作之一
  • 使用該操作的原因之一就是為了給圖像預(yù)處理的時(shí)候減低噪聲
  • 使用Smooth/Blur操作背后是數(shù)學(xué)的卷積計(jì)算 g ( i , j ) = ∑ k j f ( i + k , j + l ) h ( k , l ) g(i,j)=\sum\limits_{kj}f(i+k,j+l)h(k,l) g(i,j)=kj?f(i+k,j+l)h(k,l)
  • 通常這些卷積算子計(jì)算都是線性操作,所以又叫線性濾波
  • 歸一化盒子濾波(均值濾波)和高斯濾波(權(quán)重不一樣,會(huì)保留一些原有像素特質(zhì))
  • 相關(guān)API
    • 均值模糊: blur(Mat src,Mat dst,Size(xradius,yradius),Point(-1,-1));
    • 高斯模糊: GaussianBlur(Mat src,Mat dst,Size(11,11),sigmax,sigmay);其中Size(x,y)必須是正數(shù)而且是奇數(shù)。

均值模糊

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
	Mat src, dst;
	src = imread("test.jpg");
	if (src.empty()) {
		cout << "could not load this image..." << endl;
		return -1;
	}
	namedWindow("originalDemo", WINDOW_AUTOSIZE);
	imshow("originalDemo", src);
	blur(src, dst, Size(3, 3), Point(-1, -1));
	namedWindow("blur3Demo", WINDOW_AUTOSIZE);
	imshow("blur3Demo", dst);
	blur(src, dst, Size(5, 5), Point(-1, -1));
	namedWindow("blur5Demo", WINDOW_AUTOSIZE);
	imshow("blur5Demo", dst);
	waitKey(0);
}

高斯模糊

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
	Mat src, dst;
	src = imread("test.jpg");
	if (src.empty()) {
		cout << "could not load this image..." << endl;
		return -1;
	}
	namedWindow("originalDemo", WINDOW_AUTOSIZE);
	imshow("originalDemo", src);
	GaussianBlur(src, dst, Size(11, 11), 5, 5);
	namedWindow("GaussianBlurDemo", WINDOW_AUTOSIZE);
	imshow("GaussianBlurDemo", dst);
	//blur(src, dst, Size(5, 5), Point(-1, -1));
	//namedWindow("blur5Demo", WINDOW_AUTOSIZE);
	//imshow("blur5Demo", dst);
	waitKey(0);
}
  • 中值濾波
    • 統(tǒng)計(jì)排序?yàn)V波器
    • 中值對(duì)椒鹽噪聲有很好的抑制作用
  • 高斯雙邊濾波
    • 均值模糊無法克服邊緣像素信息丟失缺陷。原因是均值濾波是基于平均權(quán)重
    • 高斯模糊部分克服了該缺陷,但是無法完全避免,因?yàn)闆]有考慮像素值的不同
    • 高斯雙邊模糊-是邊緣保留的濾波方法,避免看邊緣信息丟失,保留了圖像輪廓不變,所以雙邊模糊需要輸入兩個(gè),一個(gè)空域kernel(空間),一個(gè)值域kernel(值)
  • 相關(guān)的API
    • 中值模糊 medianBlur(Mat src,Mat dest,ksize)
    • 雙邊模糊 bilateralFilter(src,dest,d=15,150,3);
      • 15-計(jì)算的半徑,半徑之內(nèi)的像素都會(huì)被納入計(jì)算,如果提供-1則會(huì)根據(jù)sigma space參數(shù)取值
      • 150-sigma color 決定多少差值之內(nèi)的像素會(huì)被計(jì)算
      • 3-sigma space如果d的值大于0則聲明無效,否則根據(jù)它來計(jì)算d值
      • 中值模糊的ksize大小必須大于一而且必須是奇數(shù)
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
	Mat src, dst;
	src = imread("cat1.jpg");
	if (src.empty()) {
		cout << "could not load this image..." << endl;
		return -1;
	}
	namedWindow("originalDemo", WINDOW_AUTOSIZE);
	imshow("originalDemo", src);
	//GaussianBlur(src, dst, Size(11, 11), 5, 5);
	//medianBlur(src, dst, 3);
	bilateralFilter(src, dst, 15, 150, 3);
	namedWindow("BilateralFilterDemo", WINDOW_AUTOSIZE);
	imshow("BilateralFilterDemo", dst);
	
	waitKey(0);
}

膨脹與腐蝕

形態(tài)學(xué)操作-膨脹
  • 圖像形態(tài)學(xué)操作-基于形狀的一系列圖像處理操作的合集,主要是基于集合論基礎(chǔ)上的形態(tài)學(xué)數(shù)學(xué)
  • 形態(tài)學(xué)有四個(gè)基本操作:膨脹、腐蝕、開、閉
  • 跟卷積操作類似,假設(shè)有圖像A和結(jié)構(gòu)元素B,結(jié)構(gòu)元素B在A上面移動(dòng),其中B定義其中心為錨點(diǎn)計(jì)算B覆蓋下A的最大像素值(腐蝕是最小像素值)用來替換錨點(diǎn)的像素,其中B作為結(jié)構(gòu)體可以是任意形狀
相關(guān)API
  • getStructuringElement(int shape,Size ksize,Point anchor)
    • 形狀(MORPH_RECT/MORPH_CROSS/MORPH_ELLIPSE)
    • 大小(奇數(shù))
    • 錨點(diǎn) 默認(rèn)是Point(-1,-1)意思就是中心像素
  • dilate(src,dst,kernel)
  • erode(src,dst,kernel)
動(dòng)態(tài)調(diào)整結(jié)構(gòu)元素大小
  • createTrackbar(constString&trackbarname,winname,int*value,int count,Trackbarcallback func,void* userdata=0)
    • 其中最主要的是callback函數(shù)功能。如果設(shè)置為NULL就是說只有值update,但是不會(huì)調(diào)用callback的函數(shù)
#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
void CallBack_Demo(int, void*);//回調(diào)函數(shù)
int element_size = 3;
int Max_size = 21;
Mat src, dst;
int main() 
{
	
	src = imread("cat1.jpg");
	if (!src.data) 
	{
		cout << "could not load this image.." << endl;
		return -1;
	}
	namedWindow("input image", WINDOW_AUTOSIZE);
	imshow("input image", src);
	namedWindow("output image", WINDOW_AUTOSIZE);
	createTrackbar("Element Size:", "output image", &element_size, Max_size, CallBack_Demo);
	CallBack_Demo(0, 0);
	waitKey(0);
	return 0;

}
void CallBack_Demo(int, void*)
{
	int s = element_size * 2 + 1;
	Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));
	//dilate(src, dst, structureElement, Point(-1, -1), 1);//膨脹
	erode(src, dst, structureElement, Point(-1, -1), 1);//腐蝕
	imshow("output image", dst);
	return;
}


//深入理解createTrackBar函數(shù)
#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
//void CallBack_Demo(int, void*);
int element_size = 3;
int Max_size = 21;
Mat src, dst;
void text(int, void*) {
	cout << element_size << endl;
}
int main()
{

	src = imread("cat1.jpg");
	if (!src.data)
	{
		cout << "could not load this image.." << endl;
		return -1;
	}
	namedWindow("測(cè)試窗口", WINDOW_AUTOSIZE);
	createTrackbar("數(shù)字", "測(cè)試窗口", &element_size, Max_size, text);
	text(0, 0);
	waitKey(0);
	return 0;
}


形態(tài)學(xué)操作

  • 相關(guān)API
    • morphologyEx(src,dest,CV_MOP_BLACKHAT,kernel);
    • Mat src-輸入圖像
    • Mat dest-輸出結(jié)果
    • int OPT-CV_MOP_OPEN/CV_MOP_CLOSE/CV_MOP_GRADIENT/CV_MOP_TOPHAT/CV_MOP_BLACKHAT形態(tài)學(xué)操作類型
    • Mat kernel -結(jié)構(gòu)元素
    • int Iteration-迭代次數(shù),默認(rèn)是1
  • 開操作-open
    • 先腐蝕后膨脹
    • 可以去掉較小的對(duì)象
  • 閉操作-close
    • 先膨脹后腐蝕
    • 可以填充小的洞(fill hole)
  • 形態(tài)學(xué)梯度-MOPGRADIENT
    • 膨脹減去腐蝕
    • 又稱為基本梯度(其他還包括-內(nèi)部梯度、方向梯度)
  • 頂帽-TOPHAT
    • 頂帽是原圖像與開操作之間的差值圖像
    • 計(jì)算結(jié)果是把較小的噪聲對(duì)象呈現(xiàn)出來
  • 黑帽
    • 黑帽是閉操作圖像與原圖像的差值圖像

針對(duì)二值圖像進(jìn)行處理

形態(tài)學(xué)操作應(yīng)用-提取水平與垂直線

膨脹:輸出的像素值是結(jié)構(gòu)元素覆蓋下輸入圖像的最大像素值

腐蝕:輸出的像素值是結(jié)構(gòu)元素覆蓋下輸入圖像的最小像素值

結(jié)構(gòu)元素

  • 上述膨脹與腐蝕過程可以使用任意的結(jié)構(gòu)元素
  • 常見的形狀:直線、圓、磁盤形狀等各種自定義形狀。

提取步驟

  • 輸入圖像imread
  • 轉(zhuǎn)換為灰度圖像-cvtColor
  • 轉(zhuǎn)換為二值圖像-adaptiveThreshold
    • API說明-adaptiveThreshold
    • Mat src-輸入的圖像
    • Mat dest-二值圖像
    • double maxValue-二值圖像最大值
    • int adaptiveMethod-自適應(yīng)方法,只能其中之一-ADAPTIVE_THRESH_MEAN_C,ADAPTIVE_THRESH_GAUSSIAN_C
    • int thresholdType-閾值類型(binary)
    • int blockSize-塊大?。?5)
    • double C-常量C,可以是正數(shù),0,負(fù)數(shù)(-2)
  • 定義結(jié)構(gòu)元素
  • 開操作(腐蝕+膨脹)提取水平與垂直線在結(jié)構(gòu)元素上做文章,把結(jié)構(gòu)元素定義為水平線或者垂直線
  • bitwise_not(src,dst):dst=255-src;

代碼樣例

#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
	Mat src,temp, dst;
	src = imread("0-1.jpg");
	if (src.empty()) {
		cout << "could not load this img..." << endl;
		return -1;
	}
	imshow("src", src);
	cvtColor(src, temp, COLOR_BGR2GRAY);
	adaptiveThreshold(temp, temp, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
	Mat x_kernel = getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1));
	Mat y_kernel = getStructuringElement(MORPH_RECT, Size(1,src.rows/16), Point(-1, -1));
	morphologyEx(temp, dst, MORPH_OPEN, x_kernel);
	
	bitwise_not(dst, dst);
    blur(dst,dst,Size(3,3),Point(-1,-1));
	namedWindow("x_line", WINDOW_AUTOSIZE);
	imshow("x_line", dst);
	waitKey(0);
	return 0;
}
  • 去除干擾項(xiàng) --轉(zhuǎn)換為二值圖像–定義核矩形–形態(tài)學(xué)操作–開
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
	Mat src,temp, dst;
	src = imread("ganrao.png");
	if (src.empty()) {
		cout << "could not load this img..." << endl;
		return -1;
	}
	imshow("src", src);
	cvtColor(src, temp, COLOR_BGR2GRAY);
	adaptiveThreshold(temp, temp, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);//自適應(yīng)閾值,可以轉(zhuǎn)換為二值圖像
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));//核,getstructingelement獲取結(jié)構(gòu)元素
	morphologyEx(temp, dst, MORPH_OPEN, kernel);
	//形態(tài)學(xué)操作--開--morph——open
	bitwise_not(dst, dst);

	imshow("干擾去除", dst);
	waitKey(0);
	return 0;
}

圖像上采樣與降采樣

  • 圖像金字塔概念

    • 采樣越多,分辨率越高,金字塔變換特征是不會(huì)改變的
    • 我們?cè)趫D像畜欄里中常常會(huì)調(diào)整圖像的大小,最常見的就是放大(zoom in)和縮小(zoom out),盡管幾何變換也可以實(shí)現(xiàn)圖像放大和縮小,但是這里我們介紹圖像金字塔
    • 一個(gè)圖像金字塔是一系列圖像組成,最底下一張是圖像尺寸最大,最上方的圖像尺寸最小,從孔金賞從上向下看就像一個(gè)古代的金字塔。
    • 高斯金字塔-用來對(duì)圖像進(jìn)行降采樣
      • 從底向上,逐層降采樣得到
      • 降采樣之后圖像的大小是M/2*N/2,即得到降采樣之后上一層的圖片
      • 高斯金字塔的生成過程分為兩步:
        • 對(duì)當(dāng)前層進(jìn)行高斯模糊
        • 刪除當(dāng)前層的偶數(shù)行與列
    • 拉普拉斯金字塔-用來重建一張圖片根據(jù)它的上層降采樣圖片
    • 高斯不同(Difference of Gaussian-DOG)
      • 定義:就是把一張圖像在不同的參屬下做高斯模糊之后的結(jié)果相減,得到的輸出圖像。稱為高斯不同
      • 高斯不同是圖像的內(nèi)在特征,在灰度圖像增強(qiáng)、角點(diǎn)檢測(cè)中經(jīng)常用到
  • 采樣API

    • 上采樣(pyrUp)-zoom in 放大
    • 降采樣(pyrDown)-zoom out 縮小

    如何進(jìn)行上采樣和降采樣從而得到高斯金字塔的圖像,在一個(gè)是如何對(duì)每一層進(jìn)行處理得到它的DOG,歸一化,彩色圖像通道也可做DOG

    #include<iostream>
    #include<opencv2/opencv.hpp>
    using namespace cv;
    using namespace std;
    int main(int argc, char** argv) {
    	Mat src,temp, g1,g2,dogImg;
    	src = imread("test.jpg");
    	if (src.empty()) {
    		cout << "could not load this img..." << endl;
    		return -1;
    	}
    	imshow("src", src);
    	//DOG
    	cvtColor(src, temp, COLOR_BGR2GRAY);//轉(zhuǎn)換為灰度圖像
    	GaussianBlur(temp, g1, Size(3, 3), 0, 0);//兩次高斯模糊
    	GaussianBlur(g1, g2, Size(3, 3), 0,0);
    	subtract(g1, g2, dogImg, Mat());//減去
    
    	//歸一化顯示
    	normalize(dogImg, dogImg, 255, 0, NORM_MINMAX);//用此函數(shù)也可化為0-1圖像
    	imshow("DOG Image", dogImg);
    	waitKey(0);
    	return 0;
    }
    

基本閾值操作(threshold)

  • 閾值是什么,簡單來說是把圖像分割的標(biāo)尺
閾值類型
  • 閾值二值化(threshold binary)

  • 閾值反二值化(threshold binary Inverted)

  • 閾值截?cái)?/strong>(threshold trunc)

  • 閾值取零(threshold to zero)

  • 閾值反取零(threshold to zero Inverted)

    • OTSU與TRANGLE

首先轉(zhuǎn)化為灰度圖像

閾值操作

threshold(src,dst,threshold_value,threshold_max,THRESH_TYPE);

#include<iostream>
#include<opencv2/opencv.hpp>
#include<math.h>
using namespace cv;
using namespace std;
int threshold_value = 127;//閾值
int threshold_max = 255;//最大閾值
Mat src, dst;
void threshold_Demo(int, void*);//聲明回調(diào)函數(shù)
int main(int argc, char** argv) {

	src = imread("test.jpg");
	if (src.empty()) {
		cout << "could not load this img..." << endl;
		return -1;
	}
	namedWindow("input image", WINDOW_AUTOSIZE);
	namedWindow("output image", WINDOW_AUTOSIZE);
	imshow("input image", src);
	createTrackbar("threshold", "output image", &threshold_value, threshold_max, threshold_Demo);//創(chuàng)建滑動(dòng)條
	threshold_Demo(0, 0);
	waitKey(0);
	return 0;
}
void threshold_Demo(int, void*) {
	cvtColor(src, dst, COLOR_BGR2GRAY);//轉(zhuǎn)換為灰度圖
	threshold(dst, dst, threshold_value, threshold_max, THRESH_BINARY);//轉(zhuǎn)換為二值圖像
	imshow("output image", dst); 
}


輸入輸出XML和YAML文件

  • XML,是“可擴(kuò)展表示為語言”,任何滿足XML命名規(guī)則的名稱都可以標(biāo)記,這就像不同的應(yīng)用程序打開了大門
  • YAML是以數(shù)據(jù)為中心,而不是以置標(biāo)語言為重點(diǎn)。YAML是一個(gè)可讀性高,用來表達(dá)資料序列的格式。哦內(nèi)閣制,YAML試圖用一種比XML更敏捷的方式,來完成XML所完成的任務(wù)
FileStorage類操作文件的使用引導(dǎo)

XML是使用非常廣泛的文件格式,可以利用XML或者YAML格式的文件存儲(chǔ)和還原各式各樣的數(shù)據(jù)結(jié)構(gòu)。當(dāng)然,他們還可以存儲(chǔ)和載入任意復(fù)雜的數(shù)據(jù)結(jié)構(gòu),其中就包括了OpenCV相關(guān)周邊的數(shù)據(jù)結(jié)構(gòu),以及各種原始數(shù)據(jù)類型,如整數(shù)和浮點(diǎn)數(shù)字和文本字符串。

過程:

  1. 實(shí)例化一個(gè) FileStorage類的對(duì)象,用默認(rèn)帶參數(shù)的構(gòu)造函數(shù)完成初始化,或者用 FileStorage::open()成員函數(shù)輔助初始化。
  2. 使用流操作符<<進(jìn)行文件寫入操作,或者>>進(jìn)行文件讀取操作,類似C++中的文件輸入輸出流。
  3. 使用 FileStorage::release()函數(shù)析構(gòu)掉 FileStorage類對(duì)象,同時(shí)關(guān)閉文件。
示例程序:XML和YAML文件的寫入
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<opencv2/opencv.hpp>
#include<math.h>
#include<time.h>
using namespace cv;
using namespace std;
int main() {
	//初始化
	FileStorage fs("test.yaml", FileStorage::WRITE);
	fs << "frameCount" << 5;
	time_t rawtime;
	time(&rawtime);
	fs << "calibrationDate" << asctime(localtime(&rawtime));
	Mat cameraMatrix = (Mat_<double>(3, 3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
	Mat distCoeffs = (Mat_<double>(5, 1) << 0.1, 0.01, -0.001, 0, 0);
	fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
	fs << "features" << "[";
	for (int i = 0; i < 3; i++)
	{
		int x = rand() % 640;
		int y = rand() % 480;
		uchar lbp = rand() % 256;
		fs << "{:" << "x" << x << "y" << y << "lbp" << "[:";
		for (int j = 0; j < 8; j++)
			fs << ((lbp >> j) & 1);
		fs << "]" << "}";
	}
		fs << "]";
		fs.release();
		
		return 0;
	
}

模板匹配(template match)

  • 模板也是一個(gè)小的圖像,用小圖像匹配的過程叫做模板匹配

  • 從左到右,從上到下計(jì)算匹配度

  • 計(jì)算歸一化平方不同TM_SQDIFF_NORMED -1

    • R ( x , y ) = ∑ x ′ y ′ ( T ( x ′ , y ′ ) ? I ( x + x ′ , y + y ′ ) ) 2 R(x,y)=\sum\limits_{x'y'}(T(x',y')-I(x+x',y+y'))^2 R(x,y)=xy?(T(x,y)?I(x+x,y+y))2
  • 計(jì)算歸一化相關(guān)性TM_CCORR_NORMED ----3

  • 計(jì)算歸一化相關(guān)系數(shù)TM_CCOEFF_NORMED -----5

  • 相關(guān)API介紹

    • matchTemplate(src,templ,result,method)
    • src-源圖像,必須是8-bit或者32-bit浮點(diǎn)數(shù)圖像
    • templ-模板圖像,類型與輸入圖像一致
    • result-輸出結(jié)果,必須是單通道32位浮點(diǎn)數(shù),假設(shè)源圖像W*H,模板圖像w*h,則結(jié)果必須為W-w+1,H-h+1的大小
    • int method 使用的匹配方法
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
using namespace std;
int trackbar_value = TM_CCOEFF_NORMED;//閾值,
int max_track = 5;//最大閾值/類型數(shù)目
Mat src, temp, dst;
void templateMatch_demo(int, void*);
int main(int argc, char** argv) {
	src = imread("src.jpg");
	temp = imread("template.jpg");
	if (!src.data || !temp.data) {
		cout << "could not load this image..." << endl;
		return -1;
	}
	//namedWindow("input img", WINDOW_AUTOSIZE);
	namedWindow("output img", WINDOW_AUTOSIZE);
	createTrackbar("templatemacth", "output img", &trackbar_value, max_track, templateMatch_demo);//創(chuàng)建滑動(dòng)條
	templateMatch_demo(0, 0);
	waitKey(0);
}
void templateMatch_demo(int ,void*) {
	int height = src.rows - temp.rows + 1;//格式要求:大-小+1
	int width = src.cols - temp.cols + 1;
	Mat result(width, height, CV_32FC1);//要求輸出32位單通道用于模板匹配
	matchTemplate(src, temp, result, trackbar_value,Mat());//模板匹配
	normalize(result, result, 0, 1, NORM_MINMAX,-1,Mat());//歸一化0-1圖像
	Point minLoc, maxLoc,temLoc;//定位
	src.copyTo(dst);//把源圖像給dst
	double min, max;
	minMaxLoc(result, &min, &max, &minLoc, &maxLoc,Mat());
	if (trackbar_value  TM_SQDIFF || trackbar_value  TM_SQDIFF_NORMED) {
		temLoc = minLoc;
	}
	else temLoc = maxLoc;
	
	rectangle(dst, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255),2,8);//在dst上畫出框
	rectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255),2,8);
	imshow("output img", result);
	imshow("match", dst);
}

輪廓發(fā)現(xiàn)(find contour in your image)

  • 輪廓發(fā)現(xiàn)是基于圖像邊緣提取的基礎(chǔ)尋找對(duì)象輪廓的方法。所以邊緣提取的閾值選定會(huì)影響最終輪廓發(fā)現(xiàn)效果
  • API介紹
    • findContours發(fā)現(xiàn)輪廓
      • img 輸入圖像,非0的像素被看成1,0的像素保持不變,8-bit
      • contours 全部發(fā)現(xiàn)的輪廓對(duì)象
      • hierachy 圖像的拓?fù)浣Y(jié)構(gòu),可選,該輪廓發(fā)現(xiàn)算法正是基于圖像拓?fù)浣Y(jié)構(gòu)實(shí)現(xiàn)
      • mode 輪廓返回的模式
      • method 發(fā)現(xiàn)方法
      • Point offset-Point() 輪廓像素的位移,默認(rèn)(0,0)沒有位移
    • drawContours繪制輪廓
      • img 輸出圖像
      • contours 全部發(fā)現(xiàn)的輪廓對(duì)象
      • contourldx 輪廓索引號(hào)
      • color 繪制時(shí)候顏色
      • thickness 繪制線寬
      • lineType 線的類型LINE_8
      • hierarchy 拓?fù)浣Y(jié)構(gòu)圖
      • maxlevel最大層數(shù),0表示只繪制當(dāng)前的,1表示繪制當(dāng)前及其內(nèi)嵌的輪廓
  • 過程
    • 輸入圖像轉(zhuǎn)為灰度圖像cvtColor
    • 使用Canny進(jìn)行邊緣提取,得到二值圖像
    • 使用findContours尋找輪廓
    • 使用drawContours繪制輪廓
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int threshold_value = 100;
int threshold_max = 255;
Mat src, dst;
void Demo_Contours(int, void*);
RNG rng;
int main() {
	src = imread("cat3.jpg");
	if (src.empty()) {
		cout << "could not load this image..." << endl;
		return -1;
	}
	Demo_Contours(0, 0);//contours輪廓
	waitKey(0);
	return 0;
}
void Demo_Contours(int, void*) {
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	Canny(src, dst, threshold_value, threshold_value * 2, 3, false);
//Canny(輸入,輸出,低閾值,高閾值(低閾值的2·3倍),3,false);
	findContours(dst, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//尋找輪廓
	Mat drawImg = Mat::zeros(dst.size(), CV_8UC3);//8bit3通道的彩色圖像
	for (size_t i = 0; i < contours.size(); i++) { 
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));//RNG rng生成一個(gè)隨機(jī)數(shù)。
		drawContours(drawImg, contours, i, color, 2, LINE_8, hierarchy, 0, Point(0, 0));//畫出輪廓(顏色隨機(jī)),
	}
	imshow("output", drawImg);
}

凸包-Convex Hull

  • 在一個(gè)多邊形邊緣或者內(nèi)部任意兩個(gè)點(diǎn)的連線都包含在多邊形邊界或者內(nèi)部—包含集合S中所有點(diǎn)的最小凸多邊形稱為凸包

Graham掃描算法

  • 首先選擇Y方向最低的點(diǎn)作為起始點(diǎn)P0
  • 從P0開始極坐標(biāo)掃描,依次添加p1…pn(排序順序是根據(jù)極坐標(biāo)的角度大小,逆時(shí)針方向)
  • 對(duì)每個(gè)點(diǎn)pi來說,如果添加pi點(diǎn)到凸包中導(dǎo)致一個(gè)左轉(zhuǎn)向(逆時(shí)針方向)則添加該點(diǎn)到凸包,反之則從凸包中刪除該點(diǎn)。

API說明 convexHull

  • convexHull(
  • pointd,//輸入候選點(diǎn),來自findContours
  • hull//凸包
  • bool clockwise//順時(shí)針方向
  • returnPoints)//true表示返回點(diǎn)荷屬,如果第二個(gè)參數(shù)是vector則自動(dòng)忽略

凸包代碼演示(凸包只是一個(gè)比較特殊的輪廓而已)

  • 首先把圖像從RGB轉(zhuǎn)為灰度
  • 然后再轉(zhuǎn)為二值圖像
  • 再通過發(fā)現(xiàn)輪廓得到候選點(diǎn)
  • 凸包API調(diào)用
  • 繪制顯示
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int threshold_value = 100;
int threshold_max = 255;
Mat src,src_gray;
void Thershold_Callback(int, void*);
RNG rng(12345);
const char* OUTPUT = "output";
const char* TRACKBAR = "trackbar";
int main() {
	src = imread("cat1.jpg");
	if (src.empty()) {
		cout << "could not load this image..." << endl;
		return -1;
	}
	cvtColor(src, src_gray, COLOR_BGR2GRAY);//先轉(zhuǎn)化為灰度圖像
	blur(src_gray, src_gray, Size(3, 3), Point(-1, -1));//然后進(jìn)行模糊,降低噪聲,以用來更好的二值化
	namedWindow(OUTPUT, WINDOW_AUTOSIZE);
	createTrackbar(TRACKBAR, OUTPUT, &threshold_value, threshold_max, Thershold_Callback);
	Thershold_Callback(0, 0);
	waitKey(0);
	return 0;
}
void Thershold_Callback(int, void*) {
	Mat threshold_output;
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	threshold(src_gray, threshold_output, threshold_value, threshold_max, THRESH_BINARY);//轉(zhuǎn)化為二值圖像
	findContours(threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//通過發(fā)現(xiàn)輪廓的到候選點(diǎn)
	vector<vector<Point>> hull(contours.size());
	for (size_t i = 0; i < contours.size(); i++) {
		convexHull(Mat(contours[i]), hull[i], false);
	}
	Mat dst = Mat::zeros(threshold_output.size(), CV_8UC3);
	for (size_t i = 0; i < contours.size(); i++) {
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		drawContours(dst, hull, i, color, 1, LINE_8, hierarchy, 0, Point(0, 0));
		drawContours(dst, contours, i, color, 1, LINE_8, hierarchy, 0, Point(0, 0));
	}
	imshow(OUTPUT, dst);
}

輪廓周圍繪制矩形框和圓形框

從彩色圖像轉(zhuǎn)化為灰度圖像,然后進(jìn)行模糊,然后進(jìn)行二值化處理,或者使用Canny邊緣檢測(cè)

  • API介紹
    • approxPolyDP(InputArray curve,OutputArray approxCurve,double epsilon,bool closed)基于RDP算法實(shí)現(xiàn),目的是減少多邊形輪廓點(diǎn)數(shù)
    • 輪廓周圍矩形繪制-API
      • boundingRect(InputArray points)得到輪廓周圍最小矩形左上角點(diǎn)坐標(biāo)和右下角點(diǎn)坐標(biāo),繪制一個(gè)矩形
      • minAreaRect(InputArray points)得到一個(gè)旋轉(zhuǎn)的矩形,返回旋轉(zhuǎn)矩形
    • 輪廓周圍繪制圓和橢圓-API
      • minEnclosingCircle(InputArray points)//得到最小區(qū)域圓形
        • Point2f& center //圓心位置
        • float& radius//圓的半徑
      • fitEllipse(InputArray points)得到最小橢圓
  • 步驟
    • 首先將圖像變?yōu)槎祱D像(先變?yōu)榛叶葓D像,然后進(jìn)行模糊,進(jìn)而用閾值函數(shù)變?yōu)槎祱D像,或者用canny邊緣檢測(cè)變?yōu)槎祱D像)
    • 發(fā)現(xiàn)輪廓,找到圖像輪廓(findContours)
    • 通過相關(guān)API再輪廓點(diǎn)上找到最小包含矩形和圓,旋轉(zhuǎn)矩形與橢圓。
    • 繪制他們
//壞代碼
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int threshold_value = 170;
int threshold_max = 255;
Mat src, src_gray, dst;
void Contours_Callback(int, void*);
RNG rng(12345);
const char* OUTPUT = "rectangle-Demo";
const char* TRACKBAR = "trackbar";
int main() {
	src = imread("cat1.jpg");
	if (src.empty()) {
		cout << "could not load this image..." << endl;
		return -1;
	}
	cvtColor(src, src_gray, COLOR_BGR2GRAY);//先轉(zhuǎn)化為灰度圖像
	blur(src_gray, src_gray, Size(3, 3), Point(-1, -1));//然后進(jìn)行模糊,降低噪聲,以用來更好的二值化
	namedWindow(OUTPUT, WINDOW_AUTOSIZE);
	createTrackbar(TRACKBAR, OUTPUT, &threshold_value, threshold_max, Contours_Callback);
	Contours_Callback(0, 0);
	waitKey(0);
	return 0;
}
void Contours_Callback(int, void*) {
	Mat binary_output;//把灰度圖像變?yōu)槎祱D像
	vector<vector<Point>>contours;
	vector<Vec4i> hierachy;
	threshold(src_gray, binary_output, threshold_value, threshold_max, THRESH_BINARY);
	findContours(binary_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(-1, -1));
	vector<vector<Point>>contours_ploy(contours.size());
	vector<Rect>ploy_rects(contours.size());
	vector<Point2f> ccs(contours.size());
	vector<float> radius(contours.size());

	vector<RotatedRect> minRect(contours.size());
	vector<RotatedRect> myellipse(contours.size());


	for (size_t i = 0; i < contours.size(); i++) {
		approxPolyDP(Mat(contours[i]), contours_ploy[i], 3, true);//初始化
		/*ploy_rects[i] = boundingRect(contours_ploy[i]);
		minEnclosingCircle(contours_ploy[i], ccs[i], radius[i]);*/
		if (contours_ploy.size() > 5) {
			myellipse[i] = fitEllipse(contours_ploy[i]);
			minRect[i] = minAreaRect(contours_ploy[i]);
		}
	}
	src.copyTo(dst);
	Point2f pts[4];
	for (size_t i = 0; i < contours.size(); i++) {
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		
		if (contours_ploy.size() > 5) {
		//rectangle(dst, ploy_rects[i], color, 2, LINE_8);
		//circle(dst, ccs[i], radius[i], color, 2, LINE_8);
		ellipse(dst, myellipse[i], color, 1, LINE_8);
		minRect[i].points(pts);
		for (int r = 0; r < 4; r++) {
			line(dst, pts[r], pts[(r + 1) % 4], color, 1, LINE_8);
		}
		}
		
	}
	imshow(OUTPUT, dst);
}

圖像矩(Image Moments)

持續(xù)更新…

自用整理,僅為了記錄,如需轉(zhuǎn)載請(qǐng)標(biāo)明出處。文章來源地址http://www.zghlxwxcb.cn/news/detail-774560.html

到了這里,關(guān)于opencv 入門學(xué)習(xí)筆記(C++)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 《Opencv3編程入門》學(xué)習(xí)筆記—第三章

    《Opencv3編程入門》學(xué)習(xí)筆記—第三章

    記錄一下在學(xué)習(xí)《Opencv3編程入門》這本書時(shí)遇到的問題或重要的知識(shí)點(diǎn)。 一、圖像的載入、顯示和輸出到文件 (一)OpenCV的命名空間 簡單的OpenCV程序標(biāo)配: (二)Mat類簡析 表示從指定路徑下把名為dota.jpg的圖像載入到Mat類型的srcImage 變量中。 (三)圖像的載入與顯示概述

    2024年02月08日
    瀏覽(90)
  • python+openCV (入門級(jí))車道線檢測(cè) 學(xué)習(xí)筆記

    python+openCV (入門級(jí))車道線檢測(cè) 學(xué)習(xí)筆記

    本文使用python+openCV 用到的算法: 高斯濾波 Canny邊緣檢測(cè) ROI和mask 霍夫變換 離群值過濾 最小二乘法擬合 win+x選擇運(yùn)行,然后輸入cmd 輸入 pip install opencv-python 等待安裝 在IDLE中新建腳本.py文件,輸入 import cv2 ,如果無報(bào)錯(cuò)即為安裝成功。 再輸入 print(cv2.__version__) 可查看openCV版本

    2023年04月10日
    瀏覽(22)
  • 《OpenCV 計(jì)算機(jī)視覺編程攻略》學(xué)習(xí)筆記(一:圖像編程入門)

    《OpenCV 計(jì)算機(jī)視覺編程攻略》學(xué)習(xí)筆記(一:圖像編程入門)

    參考引用 OpenCV 計(jì)算機(jī)視覺編程攻略(第3版) 說明 本書結(jié)合 C++ 和 OpenCV 3.2 全面講解計(jì)算機(jī)視覺編程 所有代碼均在 Ubuntu 系統(tǒng)中用 g++ 編譯執(zhí)行 0. 安裝 OpenCV 庫 在Ubuntu上安裝OpenCV及使用 OpenCV 庫分為多個(gè)模塊 ,常見模塊如下 opencv_core 模塊包含庫的核心功能 opencv_imgproc 模塊包

    2024年02月09日
    瀏覽(49)
  • 【計(jì)算機(jī)視覺—python 】 圖像處理入門教程 —— 圖像屬性、像素編輯、創(chuàng)建與復(fù)制、裁剪與拼接【 openCV 學(xué)習(xí)筆記 005 to 010 and 255】

    【計(jì)算機(jī)視覺—python 】 圖像處理入門教程 —— 圖像屬性、像素編輯、創(chuàng)建與復(fù)制、裁剪與拼接【 openCV 學(xué)習(xí)筆記 005 to 010 and 255】

    OpenCV中讀取圖像文件后的數(shù)據(jù)結(jié)構(gòu)符合Numpy的ndarray多維數(shù)組結(jié)構(gòu),因此 ndarray 數(shù)組的屬性和操作方法可用于圖像處理的一些操作。數(shù)據(jù)結(jié)構(gòu)如下圖所示: img.ndim:查看代表圖像的維度。彩色圖像的維數(shù)為3,灰度圖像的維度為2。 img.shape:查看圖像的形狀,代表矩陣的行數(shù)(高

    2024年01月19日
    瀏覽(104)
  • OpenCV入門基礎(chǔ)學(xué)習(xí)

    OpenCV入門基礎(chǔ)學(xué)習(xí)

    目錄 一:OpenCV簡介 二:OpenCV圖像處理? ?圖像 三:OpenCV圖像處理? ?圖像模式? 四:OpenCV圖像識(shí)別? 圖片操作 五:OpenCV圖像處理? ?Mat類 六:OpenCV圖像處理? ?圖片? 像素 七:OpenCV圖像處理的使用? ?視頻操作 OpenCV于1999年由Gary Bradsky在英特爾創(chuàng)立,第一個(gè)版本于2000年問世

    2024年02月07日
    瀏覽(21)
  • OpenCV學(xué)習(xí)筆記 使用OpenCV進(jìn)行人臉交換

    ? ? ? ? 首先說換臉這件事情,已經(jīng)可以算是有一丟丟古老的技術(shù)了,基于OpenCV進(jìn)行人臉交換的好處在于簡單,壞處在于無法復(fù)刻表情。如果想要比較完美的可以去找deepfakes相關(guān)技術(shù),如果想要對(duì)臉部進(jìn)行一些自定義操作,那么了解OpenCV換臉涉及到的技術(shù)點(diǎn)還是有價(jià)值的。

    2024年03月11日
    瀏覽(20)
  • OpenCV-空間濾波學(xué)習(xí)筆記

    OpenCV-空間濾波學(xué)習(xí)筆記

    了解和實(shí)踐OpenCV在空間濾波上的應(yīng)用。 Source:機(jī)器視覺技術(shù)與應(yīng)用_中國大學(xué)MOOC(慕課) (icourse163.org) 當(dāng)圖像中的邊緣信息和卷積核的形狀是相符合的,得到的響應(yīng)值最大。 中值濾波 均值濾波 高斯均值濾波 Sobel邊緣提取 中值濾波 實(shí)驗(yàn)用圖 帶有椒鹽噪聲的圖像: 實(shí)驗(yàn)代碼 #i

    2024年01月17日
    瀏覽(17)
  • opencv/openmv學(xué)習(xí)筆記

    opencv/openmv學(xué)習(xí)筆記

    首先區(qū)分CV與MV: OpenCV是一個(gè)開源視覺庫,不包括硬件;而OpenMV則是一個(gè)硬件和軟件搭配的攝像頭小型模塊。 python配置: 下載好適合的python版本:https://www.python.org/doc/versions/zh-cn/ 下載PyCharm:https://www.jetbrains.com/pycharm/promo/anaconda/ 在PyCharm中安裝“opencv-python”與“opencv-contrib

    2024年02月13日
    瀏覽(15)
  • (9)OpenCV深度學(xué)習(xí)系列教程——PyTorch入門

    作者:禪與計(jì)算機(jī)程序設(shè)計(jì)藝術(shù) PyTorch是一個(gè)由Facebook開發(fā)的開源機(jī)器學(xué)習(xí)框架,它提供了一整套用于訓(xùn)練、評(píng)估和部署深度學(xué)習(xí)模型的工具和方法。隨著深度學(xué)習(xí)在各個(gè)領(lǐng)域的應(yīng)用越來越廣泛,PyTorch作為一個(gè)成熟的框架已經(jīng)成為機(jī)器學(xué)習(xí)研究人員的必備工具。本系列教程從

    2024年02月07日
    瀏覽(26)
  • OpenCV學(xué)習(xí)筆記(一)——Anaconda下載和OpenCV的下載

    OpenCV學(xué)習(xí)筆記(一)——Anaconda下載和OpenCV的下載

    OpenCV是圖象識(shí)別中有巨大的應(yīng)用場(chǎng)景,本篇文章以Python為基礎(chǔ)。當(dāng)初學(xué)OpenCV的時(shí)候,推使用在Anaconda編寫代碼,原因比較方便,下面我們對(duì)于Anaconda的下載過程進(jìn)行演示。 Anaconda的下載 首先打開官網(wǎng)www.anaconda.com/download找到download按鈕點(diǎn)擊: 下載完成之后點(diǎn)擊安裝包 之后出現(xiàn)

    2024年04月17日
    瀏覽(17)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包