实践教程 | 万字长文,值得收藏/参考的OpenCV C++基础代码
點擊上方“3D視覺工坊”,選擇“星標(biāo)”
干貨第一時間送達(dá)
作者丨卡拉肖克-X
來源丨OpenCV學(xué)堂
編輯丨極市平臺
導(dǎo)讀
?一位友好人士做的B站OpenCV4.x C++ 快速入門30講視頻課程的筆記總結(jié)!
01 環(huán)境搭建
環(huán)境配置了一個早上,到10.48分配置完畢,有點難受。還好最后顯示出第一張圖片。
#include<opencv2/opencv.hpp> #include<iostream>usingnamespacestd; usingnamespace cv; int main() {Mat src = imread("D:/images/011.jpg",IMREAD_GRAYSCALE);//讀取進(jìn)來的數(shù)據(jù)以矩陣的形勢,第二個參數(shù)代表顯示一張灰度圖像。if (src.empty()) {printf("could not load image");//如果圖片不存在 將無法讀取,打印到終端。}//超過屏幕的圖像無法顯示時候調(diào)用此函數(shù)。namedWindow("輸入窗口", WINDOW_FREERATIO);//創(chuàng)建了一個新窗口,參數(shù)1表示名稱,第二個參數(shù)代表一個自由的比例imshow("輸入窗口", src);//表示顯示在新創(chuàng)建的輸入窗口上,第一個參數(shù)表示窗口名稱,src表示數(shù)據(jù)對象Mat waitKey(0);//執(zhí)行到這句,程序阻塞。參數(shù)表示延時時間。單位msdestroyAllWindows();//銷毀前面創(chuàng)建的顯示窗口return0; }第一節(jié)課介紹了如何讀取第一張圖片,并且顯示出來,通過調(diào)用imread函數(shù)讀取照片,再調(diào)用imshow顯示圖片到窗口。同時,講述了如何打印灰度圖像,圖片讀取失敗的處理方式,代碼注釋詳細(xì)介紹了每條語句的意思。
02 顯示圖象
1、色彩空間轉(zhuǎn)換函數(shù) cvtColor
2、圖像的保存
這節(jié)主要介紹了創(chuàng)建一個類對象,然后通過類對象調(diào)用函數(shù),在main主函數(shù)中進(jìn)行調(diào)用實現(xiàn)類對象中的功能,比如轉(zhuǎn)換成HSV類型圖片和GRAY類型圖片,最后通過imwrite函數(shù)進(jìn)行圖像的保存。
03 圖像對象的創(chuàng)建與賦值
1、怎么操作mat
2、怎么訪問每一個像素點
3、怎么創(chuàng)建一個空圖或者mat
本節(jié)課介紹了如何創(chuàng)建一個Mat對象,通過創(chuàng)建新的Mat對象來創(chuàng)建用戶的特定的底色畫布,創(chuàng)建圖像的基本類型有兩種一種是ones一種是zeros,ones()中的第一個參數(shù)代表圖像的大小,第二個參數(shù)代表創(chuàng)建幾維的圖像,UC代表無符號字符型,數(shù)組3代表通道數(shù)。克隆和賦值的區(qū)別,克隆就是產(chǎn)生一個新的對象,新對象改變屬性,舊對象屬性不變(各自為政)。賦值是二者同體,當(dāng)新屬性發(fā)生改變,舊屬性也發(fā)生改變(二者同體)。
04 圖像像素的讀寫操作
如何遍歷和修改每個像素點的數(shù)值,分為單通道和多通道。訪問模式模式也有兩種。第一種是數(shù)組訪問模式,用最常規(guī)的數(shù)組下標(biāo)訪問像素值。
void QuickDemo::pixel_visit_demo(Mat &image) {int dims = image.channels();int h = image.rows;int w = image.cols;for (int row = 0; row < h; row++) {for (int col = 0; col < w; col++) {if (dims == 1) //單通道的灰度圖像{int pv = image.at<uchar>(row, col);//得到像素值image.at<uchar>(row, col) = 255 - pv;//給像素值重新賦值}if (dims == 3) //三通道的彩色圖像{Vec3b bgr = image.at<Vec3b>(row, col); //opencv特定的類型,獲取三維顏色,3個值image.at<Vec3b>(row, col)[0] = 255 - bgr[0];image.at<Vec3b>(row, col)[1] = 255 - bgr[1];image.at<Vec3b>(row, col)[2] = 255 - bgr[2];//對彩色圖像讀取它的像素值,并且對像素值進(jìn)行改寫。}}}namedWindow("像素讀寫演示", WINDOW_FREERATIO);imshow("像素讀寫演示", image); }第二種為指針訪問模式,指定一個指針為圖片的首地址,通過循環(huán)遍歷,指針++,一次往后推。
void QuickDemo::pixel_visit_demo(Mat &image) {int dims = image.channels();int h = image.rows;int w = image.cols;for (int row = 0; row < h; row++){uchar *current_row = image.ptr<uchar>(row);for (int col = 0; col < w; col++){if (dims == 1) //單通道的灰度圖像{int pv = *current_row;//得到像素值*current_row++ = 255 - pv;//給像素值重新賦值}if (dims == 3) //三通道的彩色圖像{*current_row++ = 255 - *current_row; //指針每做一次運(yùn)算,就向后移動一位*current_row++ = 255 - *current_row;*current_row++ = 255 - *current_row;}}}namedWindow("像素讀寫演示", WINDOW_FREERATIO);imshow("像素讀寫演示", image);}本節(jié)主要介紹了通過兩種遍歷的方式訪問圖像的像素值,并且改變圖像的像素值。
05 圖像像素的操作
對圖像的各個像素點實現(xiàn)加減乘除的操作。介紹了常用的除爆函數(shù)saturate_cast,防止數(shù)值過界。
void QuickDemo::operators_demo(Mat &image) {Mat dst = Mat::zeros(image.size(), image.type());Mat m = Mat::zeros(image.size(), image.type());dst = image - Scalar(50, 50, 50);m = Scalar(50, 50, 50);multiply(image,m,dst);//乘法操作 apiimshow("乘法操作", dst);add(image, m, dst);//加法操作 apiimshow("加法操作", dst);subtract(image, m, dst);//減法操作 apiimshow("減法操作", dst);divide(image, m, dst);//除法操作 apinamedWindow("加法操作", WINDOW_FREERATIO);imshow("加法操作", dst);//加法操作底層int dims = image.channels();int h = image.rows;int w = image.cols;for (int row = 0; row < h; row++){for (int col = 0; col < w; col++){Vec3b p1 = image.at<Vec3b>(row, col); //opencv特定的類型,獲取三維顏色,3個值Vec3b p2 = m.at<Vec3b>(row, col);dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(p1[0] + p2[0]);//saturate_cast用來防爆,小于0就是0,大于255就是255dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(p1[1] + p2[1]);dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(p1[2] + p2[2]);//對彩色圖像讀取它的像素值,并且對像素值進(jìn)行改寫。}}imshow("加法操作", dst); }介紹了四種不同的API實現(xiàn),并且演示了一種加法的算法。
06 滾動條演示操作-調(diào)整圖片亮度
本節(jié)介紹怎么通過createTrackbar來設(shè)置一個進(jìn)度條,實現(xiàn)圖片的亮度調(diào)節(jié)。
Mat src, dst, m; int lightness = 50;//定義初始的亮度為50 static void on_track(int ,void*) {m = Scalar(lightness,lightness,lightness);//創(chuàng)建調(diào)整亮度的數(shù)值subtract(src, m, dst);//定義亮度變化為減imshow("亮度調(diào)整", dst);//顯示調(diào)整亮度之后的圖片 } void QuickDemo::tracking_bar_demo(Mat &image) {namedWindow("亮度調(diào)整",WINDOW_AUTOSIZE);dst = Mat::zeros(image.size(), image.type());//圖片的初始化創(chuàng)建一個和image大小相等,種類相同的圖像m = Mat::zeros(image.size(), image.type());//圖片的初始化創(chuàng)建一個和image大小相等,種類相同的圖像src = image;//給src賦值int max_value = 100;//定義最大值為100createTrackbar("Value Bar:", "亮度調(diào)整", &lightness, max_value,on_track);//調(diào)用函數(shù)實現(xiàn)功能。on_track(50, 0); }07 滾動條演示操作-傳遞參數(shù)
無類型指針類型轉(zhuǎn)換與參數(shù)傳遞!
static void on_lightness(int b ,void* userdata) {Mat image = *((Mat*)userdata);Mat dst = Mat::zeros(image.size(), image.type());Mat m = Mat::zeros(image.size(), image.type());m = Scalar(b,b,b);addWeighted(image,1.0,m,0,b,dst);//融合兩張圖imshow("亮度&對比度調(diào)整", dst); } static void on_contrast(int b, void* userdata) {Mat image = *((Mat*)userdata);Mat dst = Mat::zeros(image.size(), image.type());Mat m = Mat::zeros(image.size(), image.type());double contrast = b / 100.0;addWeighted(image, contrast, m, 0.0, 0, dst);//融合兩張圖imshow("亮度&對比度調(diào)整", dst); } void QuickDemo::tracking_bar_demo(Mat &image) {namedWindow("亮度&對比度調(diào)整",WINDOW_AUTOSIZE);int lightness = 50;int max_value = 100;int contrast_value = 100;createTrackbar("Value Bar:", "亮度&對比度調(diào)整", &lightness, max_value, on_lightness,(void*)(&image));createTrackbar("Contrast Bar:", "亮度&對比度調(diào)整", &contrast_value, 200, on_contrast, (void*)(&image));on_lightness(50, &image); }08 鍵盤響應(yīng)操作
本節(jié)介紹通過鍵盤輸入,終端能夠讀取響應(yīng)的信息。
void QuickDemo::key_demo(Mat &image) {Mat dst= Mat::zeros(image.size(), image.type());while (true) {char c = waitKey(100);//停頓100ms 做視頻處理都是1if (c == 27) { //esc 退出應(yīng)用程序break;}if (c == 49)//key#1{std::cout <<"you enter key #1" << std::endl;cvtColor(image, dst, COLOR_BGR2GRAY);}if (c == 50)//key#1{std::cout << "you enter key #2" << std::endl;cvtColor(image, dst, COLOR_BGR2HSV);}if (c == 51)//key#1{std::cout << "you enter key #3" << std::endl;dst = Scalar(50, 50, 50);add(image,dst,dst);}imshow("鍵盤響應(yīng)",dst);std::cout << c << std::endl;} }通過鍵盤輸入,在終端得到響應(yīng),輸入不同的鍵值,得到不一樣的結(jié)果。
09 opencv自帶顏色操作
void QuickDemo::color_style_demo(Mat &image) {int colormap[] = {COLORMAP_AUTUMN ,COLORMAP_BONE,COLORMAP_CIVIDIS,COLORMAP_DEEPGREEN,COLORMAP_HOT,COLORMAP_HSV,COLORMAP_INFERNO,COLORMAP_JET,COLORMAP_MAGMA,COLORMAP_OCEAN,COLORMAP_PINK,COLORMAP_PARULA,COLORMAP_RAINBOW,COLORMAP_SPRING,COLORMAP_TWILIGHT,COLORMAP_TURBO,COLORMAP_TWILIGHT,COLORMAP_VIRIDIS,COLORMAP_TWILIGHT_SHIFTED,COLORMAP_WINTER};Mat dst;int index = 0;while (true) {char c = waitKey(100);//停頓100ms 做視頻處理都是1if (c == 27) { //esc 退出應(yīng)用程序break;}if (c == 49)//key#1 按下按鍵1時,保存圖片到指定位置{std::cout << "you enter key #1" << std::endl;imwrite("D:/gray.jpg", dst);}applyColorMap(image, dst, colormap[index%19]);//循環(huán)展示19種圖片index++;imshow("循環(huán)播放", dst);} }偽色彩填充與顏色表匹配
10 圖像像素的邏輯操作
本節(jié)介紹如何對圖像的像素進(jìn)行操作,包括與、或、非、異或,矩形在圖像中的繪制。
void QuickDemo::bitwise_demo(Mat &image) {Mat m1 = Mat::zeros(Size(256,256),CV_8UC3);Mat m2 = Mat::zeros(Size(256,256),CV_8UC3);rectangle(m1,Rect(100,100,80,80),Scalar(255,255,0),-1,LINE_8,0);//小于0表示填充,大于0表示繪制rectangle(m2,Rect(150,150,80,80), Scalar(0,255,255), -1, LINE_8, 0);imshow("m1", m1);imshow("m2", m2);Mat dst;bitwise_and(m1, m2, dst);//位操作與bitwise_or(m1, m2, dst);//位操作或bitwise_not(image, dst);//取反操作bitwise_xor(m1, m2, dst);//異或操作imshow("像素位操作", dst); } rectangle(m1,Rect(100,100,80,80),Scalar(255,255,0),-1,LINE_8,0);這個函數(shù)參數(shù)1是圖片名稱,參數(shù)2是矩形的起始&末尾位置,參數(shù)3 Scalar表示將要繪制圖像的顏色,參數(shù)4表示小于0表示填充,大于0表示繪制,參數(shù)5表示四鄰域或者八鄰域的繪制,參數(shù)6表示中心坐標(biāo)或者半徑坐標(biāo)的小數(shù)位數(shù)。
11 通道的分離與合并
本節(jié)介紹如何把不同的通道給分離,歸并,使得能顯現(xiàn)出來不同的通道顏色。
void QuickDemo::channels_demo(Mat &image) { std::vector<Mat>mv;split(image, mv);//imshow("藍(lán)色", mv[0]);//0,1,2三個通道分別代表BGR。//關(guān)閉2個通道意味著開啟一個通道。//imshow("綠色", mv[1]);//imshow("紅色", mv[2]);Mat dst;mv[0] = 0;mv[2] = 0;merge(mv, dst);imshow("藍(lán)色", dst);int from_to[] = { 0,2,1,1,2,0 };//把通道相互交換,第0->第2,第一->第一,第二->第0mixChannels(&image,1,&dst,1,from_to,3);//3表示3個通道//參數(shù)1指針引用圖像->參數(shù)2引用到dstimshow("通道混合", dst); }M[0],M[1],M[2]分別代表BGR個不同的通道。要開啟某個通道只需要關(guān)閉另外的一個通道即可。第二個內(nèi)容為通道的合并,將不同通道的像素值進(jìn)行轉(zhuǎn)換操作,使圖片呈現(xiàn)出不同的效果。
12 圖像色彩空間轉(zhuǎn)換
本節(jié)內(nèi)容實現(xiàn)任務(wù)是提取任務(wù)的輪廓,首先把RGB色彩空間的圖片轉(zhuǎn)換到HSV空間中,其次,提取圖片的mask,通過使用inrangle提取hsv色彩空間的顏色。HSV色彩空間的顏色
void QuickDemo::inrange_demo(Mat &image) {Mat hsv;cvtColor(image, hsv, COLOR_BGR2HSV);Mat mask;inRange(hsv,Scalar(35,43,46),Scalar(77,255,255),mask);//35,43,46根據(jù)圖片中綠色最低來確定最小值。//77,255,255 提取//參數(shù)1低范圍,參數(shù)2高范圍//將hsv中的由低到高的像素點提取出來并且存儲到mask當(dāng)中。imshow("mask",hsv);Mat redback = Mat::zeros(image.size(), image.type());redback = Scalar(40, 40, 200);bitwise_not(mask, mask);imshow("mask", mask);image.copyTo(redback, mask);//把redback復(fù)制到mask,mask通過inRange得到。imshow("roi提取", hsv); }13 圖像像素值統(tǒng)計
分別定義雙精度型變量 minv和maxv。指針變量minLoc,maxLoc;因為這圖片是多通道的,所以使用一個容器裝取數(shù)值,并且用split分離圖片到MV中通過for循環(huán)操作,遍歷圖片信息,并且打印信息到終端。圖像信息包括,方差,均值,大小。
void QuickDemo::pixel_statistic_demo(Mat &image) {double minv, maxv;//定義最值Point minLoc, maxLoc;//定義最值地址std::vector<Mat>mv;//mv是一個Mat類型的容器 裝在這個容器內(nèi)split(image, mv);for (int i = 0; i < mv.size(); i++) {//分別打印各個通道的數(shù)值minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());//求出圖像的最大值和最小值。std::cout <<"No.channels:"<<i<<"minvalue:" << minv << "maxvalue:" << maxv << std::endl;}Mat mean, stddev;meanStdDev(image, mean, stddev);//求出圖像的均值和方差std::cout << "mean:" << mean << std::endl;std::cout << "stddev:" << stddev << std::endl; }14 圖像幾何形狀的繪制
本節(jié)課介紹如何繪制橢圓,矩形,直線,圓等
void QuickDemo::drawing_demo(Mat &image) {Rect rect;rect.x = 200;rect.y = 200;rect.width = 100;rect.height = 100;Mat bg = Mat::zeros(image.size(),image.type());rectangle(image, rect, Scalar(0, 0, 255), -1, 8, 0);//參數(shù)1為繪圖的底圖或者畫布名稱,參數(shù)2位圖片的起始,寬度,高度//參數(shù)3代表填充顏色。參數(shù)4大于0是線小于0是填充//參數(shù)5表示鄰域填充,參數(shù)6默認(rèn)值為0circle(bg, Point(350, 400), 15, Scalar(0, 0, 255), 2, LINE_AA, 0);//參數(shù)2位圖片中心位置,參數(shù)3為半徑為15的圓Mat dst;//addWeighted(image, 0.7, bg, 0.3, 0, dst);RotatedRect rtt;rtt.center = Point(200, 200);rtt.size = Size(100, 200);rtt.angle = 0.0;line(bg,Point(100,100),Point(350,400), Scalar(0, 0, 255), 8, LINE_AA, 0);//line_AA表示去掉鋸齒ellipse(bg,rtt, Scalar(0, 0, 255), 2, 8);imshow("矩形的繪制",bg); }15 隨機(jī)數(shù)與隨機(jī)顏色
本節(jié)主要介紹如何能產(chǎn)生一個隨機(jī)數(shù)字和隨機(jī)顏色,并且用線條的方式顯示出來。
void QuickDemo::random_drawing() {Mat canvas = Mat::zeros(Size(512,512), CV_8UC3);int w = canvas.cols;int h = canvas.rows;RNG rng(12345);while (true) {int c = waitKey(10);if (c == 27) {break;}int x1 = rng.uniform(0,canvas.cols);int y1 = rng.uniform(0, h);int x2 = rng.uniform(0, canvas.cols);int y2 = rng.uniform(0, h);int b = rng.uniform(0, 255);int g = rng.uniform(0, 255);int r = rng.uniform(0, 255);canvas = Scalar(0,0,0);line(canvas, Point(x1, y1), Point(x2, y2), Scalar(b,g,r), 8, LINE_AA,0);//line_AA表示去掉鋸齒 imshow("隨機(jī)繪制演示", canvas);} }16 多邊形填充與繪制
這節(jié)課介紹了2種多邊形繪制的實現(xiàn)方式。
void QuickDemo::polyline_drawing_demo(Mat &image) {Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);Point p1(100, 100);Point p2(350, 100);Point p3(450, 280);Point p4(320, 450);Point p5(80, 400);std::vector<Point>pts;//將5個點裝入一個容器內(nèi)。pts.push_back(p1);//未初始化數(shù)組容量,只能用pushback操作//如果初始化,可以用數(shù)組下標(biāo)操作。pts.push_back(p2);pts.push_back(p3);pts.push_back(p4);pts.push_back(p5);//fillPoly(canvas, pts, Scalar(122, 155, 255), 8, 0);//填充多邊形//polylines(canvas, pts, true, Scalar(0, 0, 255), 2, 8, 0);//繪制多邊形/*參數(shù)1表示畫布,參數(shù)2表示點集,參數(shù)3表示true,參數(shù)4顏色參數(shù)5表示線寬,參數(shù)6表示渲染方式,參數(shù)7表示相對左上角(0,0)的位置*///單個API搞定圖片的繪制填充std::vector<std::vector<Point>>contours;contours.push_back(pts);drawContours(canvas,contours,-1, Scalar(0, 0, 255),-1);//參數(shù)2表示容器名稱,參數(shù)3為正表示多邊形的繪制,為負(fù)表示多邊形的填充imshow("多邊形繪制", canvas); }第一種方式,通過標(biāo)記各個點,然后存儲到容器中,之后對容器中的點進(jìn)行操作。填充多邊形調(diào)用fillPoly,繪制多邊形調(diào)用polylines。第二種方式,使用一個API接口繪制。通過一個容器中的存儲的點組成的另一個容器。
17 鼠標(biāo)操作與響應(yīng)
鼠標(biāo)事件響應(yīng)與繪制!考察基本的圖形繪制編程能力。
//參數(shù)1表示鼠標(biāo)事件。 Point sp(-1, -1);//鼠標(biāo)的開始的位置 Point ep(-1, -1); Mat temp; static void on_draw(int event,int x,int y,int flags,void *userdata) {Mat image = *((Mat*)userdata);if(event == EVENT_LBUTTONDOWN)//如果鼠標(biāo)的左鍵按下{sp.x = x;sp.y = y;std::cout << "start point" <<sp<< std::endl;}elseif (event == EVENT_LBUTTONUP){ep.x = x;ep.y = y;int dx = ep.x - sp.x;int dy = ep.y - sp.y;if (dx > 0 && dy > 0) {Rect box(sp.x, sp.y, dx, dy);imshow("ROI區(qū)域", image(box));rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);imshow("鼠標(biāo)繪制", image);sp.x = -1;sp.y = -1;//復(fù)位,為下一次做準(zhǔn)備}}elseif (event == EVENT_MOUSEMOVE) {if (sp.x > 0 && sp.y > 0){ep.x = x;ep.y = y;int dx = ep.x - sp.x;int dy = ep.y - sp.y;if (dx > 0 && dy > 0){Rect box(sp.x, sp.y, dx, dy);temp.copyTo(image);rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);imshow("鼠標(biāo)繪制", image);}}} } void QuickDemo::mouse_drawing_demo(Mat &image) {namedWindow("鼠標(biāo)繪制", WINDOW_AUTOSIZE);setMouseCallback("鼠標(biāo)繪制", on_draw,(void*)(&image));//設(shè)置窗口的回調(diào)函數(shù)。參數(shù)1表示名稱,參數(shù)2表示調(diào)用on_drawimshow("鼠標(biāo)繪制", image);temp = image.clone(); }18 圖像像素類型的轉(zhuǎn)換與歸一化
像素值歸一化是很常見的預(yù)處理方式,OpenCV支持字節(jié)與浮點數(shù)的圖象顯示。
void QuickDemo::norm_demo(Mat &image) {Mat dst;//定義一個名為dst的二值化類型的數(shù)據(jù)std::cout << image.type() << std::endl;//打印出來圖片的類型image.convertTo(image,CV_32F);//將dst數(shù)據(jù)轉(zhuǎn)換成浮點型float32位數(shù)據(jù)。std::cout << image.type() << std::endl;//再次打印轉(zhuǎn)換后的數(shù)據(jù)類型normalize(image, dst, 1.0, 0, NORM_MINMAX);//進(jìn)行歸一化操作std::cout << dst.type() << std::endl;//打印歸一化操作之后的數(shù)據(jù)imshow("圖像的歸一化", dst);//顯示歸一化的圖像//CV_8UC3 ,CV_32FC3 //3通道每個通道8位的UC類型//轉(zhuǎn)換后 3通道 每個通道32位的浮點數(shù) }19 圖像的放縮與插值
介紹基本的圖像變換大小的方法。圖像的差值處理主要有線性、雙線性差值、盧卡斯差值、雙立方差值。
void QuickDemo::resize_demo(Mat &image) {Mat zoomin, zoomout;int h = image.rows;int w = image.cols;resize(image, zoomin, Size(w/2, h/2),0,0,INTER_LINEAR);//線性差值操作。imshow("zoomin", zoomin);; resize(image, zoomout, Size(w*1.5, h*1.5), 0, 0, INTER_LINEAR);imshow("zoomin", zoomout);// }20 圖像的翻轉(zhuǎn)
圖像的上下、左右、對角線翻轉(zhuǎn)
void QuickDemo::flip_demo(Mat &image) {Mat dst;flip(image, dst, 0);//上下翻轉(zhuǎn) x對稱flip(image, dst, 1);//左右翻轉(zhuǎn) y對稱flip(image, dst, -1);//旋轉(zhuǎn)180°imshow("圖像翻轉(zhuǎn)",dst); }21 圖像的旋轉(zhuǎn)
圖像旋轉(zhuǎn)的基本原理,變換矩陣M的計算,中心位置偏移計算等。
void QuickDemo::rotate_demo(Mat &image) {Mat dst, M;int h = image.rows;//定義圖片的高度int w = image.cols;//定義圖片的寬度M = getRotationMatrix2D(Point(w / 2, h / 2),45,1.0);doublecos = abs(M.at<double>(0, 0));doublesin = abs(M.at<double>(0, 1));int nw = cos * w + sin * h;int nh = sin * w + cos * h;M.at<double>(0, 2) += (nw / 2 - w / 2);M.at<double>(1, 2) += (nh / 2 - h / 2);//參數(shù)1原來圖像的中心位置。參數(shù)2角度是多少。參數(shù)3是圖像本身大小的放大縮小warpAffine(image, dst, M,Size(nw,nh),INTER_LINEAR,0, Scalar(0, 0, 255));imshow("旋轉(zhuǎn)演示", dst); }22 視頻文件攝像頭使用
本節(jié)介紹了如何讀取一個視頻,以及調(diào)用電腦的攝像頭。并且對讀取到的視頻進(jìn)行操作。
void QuickDemo::video_demo(Mat &image) {VideoCapture capture("D:/images/123.mp4"); //讀取視頻的地址Mat frame;//定義一個二值化的 framewhile (true){capture.read(frame); //讀取視頻//flip(frame, frame, 1);//圖像鏡像操作if(frame.empty())//如果視頻為空的話 跳出操作{break;}imshow("frame", frame);//顯示視頻colorSpace_Demo(frame);//對視頻調(diào)用之前的demoint c = waitKey(100);//停頓100ms 做視頻處理都是1if (c == 27) { //esc 退出應(yīng)用程序break;}}capture.release();//釋放相機(jī)的資源 }對讀取到的視頻 操作方式有鏡像對稱。加各種濾鏡等等。
23 視頻處理與保存
視頻的屬性,SD(標(biāo)清),HD(高清),UHD(超清),藍(lán)光。如何讀取視頻文件,以及讀取視頻文件的屬性,衡量視頻處理指標(biāo):FPS。保存視頻時的編碼格式。保存視頻的實際size和create的size大小保持一致。
void QuickDemo::video_demo(Mat &image) {VideoCapture capture("D:/images/123.mp4");int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);//獲取視頻的寬度int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);//獲取視頻的高度int count = capture.get(CAP_PROP_FRAME_COUNT);//視頻總的幀數(shù)//fps是衡量處理視頻的能力double fps = capture.get(CAP_PROP_FPS);std::cout << "frame width" << frame_width << std::endl;std::cout << "frame height" << frame_height << std::endl;std::cout << "frame FPS" << fps << std::endl;std::cout << "frame count" << count << std::endl;VideoWriter writer("D:/test.mp4",capture.get(CAP_PROP_FOURCC),fps,Size(frame_width, frame_height),true);//參數(shù)1 保存地址。參數(shù)2 獲取圖片的格式 參數(shù)3 圖片的幀數(shù) 參數(shù)4 視頻寬高 參數(shù)5 真Mat frame;while (true){capture.read(frame);//flip(frame, frame, 1);//圖像鏡像操作if(frame.empty()){break;}imshow("frame", frame);colorSpace_Demo(frame);writer.write(frame);int c = waitKey(100);//停頓100ms 做視頻處理都是1if (c == 27) { //esc 退出應(yīng)用程序break;}}capture.release();//釋放相機(jī)的資源writer.release();//釋放存放的資源 }本節(jié)課,介紹了視頻的一些基本熟悉,緊接介紹如何獲取視頻的屬性,并且通過特定的格式保存到相應(yīng)的存儲位置上。
24 圖像的直方圖
直方圖是圖像的統(tǒng)計學(xué)特征。表示了圖像的各個像素在0-255出現(xiàn)的頻率。圖像的平移旋轉(zhuǎn)都不會對性質(zhì)進(jìn)行改變。缺點:不能表征一張圖像。
25 直方圖的均衡化
用途:用于圖像增強(qiáng),人臉檢測,衛(wèi)星遙感。均衡化的圖像只支持單通道。
void QuickDemo::histogram_eq_demo(Mat &image) {Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);//直方圖均衡化只支持灰度圖像,不支持彩色圖像。imshow("灰度圖像", gray);Mat dst;equalizeHist(gray, dst);imshow("直方圖均衡化", dst); }26 圖像的卷積操作
卷積的作用,高的往下降,低的往上升。但是會造成信息丟失。產(chǎn)生模糊效果。是一種線性操作,點乘,之后相加。
void QuickDemo::blur_demo(Mat &image) {Mat dst;blur(image, dst, Size(15, 15), Point(-1, -1));//參數(shù)1原始圖像,參數(shù)2卷積之后的圖像,參數(shù)3卷積的矩陣大小,支持單行或者單列的卷積操作,參數(shù)4卷積的起始點。imshow("圖像卷積操作", dst); }27 高斯模糊
中心的數(shù)值最大,離中心距離越遠(yuǎn),數(shù)值越小。高斯卷積數(shù)學(xué)表達(dá)式說明:
28 高斯雙邊模糊
邊緣保留的濾波算法!去噪!
void QuickDemo::bifilter_demo(Mat &image) {Mat dst;bilateralFilter(image,dst,0,100,0);//參數(shù)1代表原圖,參數(shù)2代表處理之后的圖像,參數(shù)3色彩空間。參數(shù)4表示坐標(biāo)空間,雙邊是指 色彩空間和坐標(biāo)空間。namedWindow("雙邊模糊", WINDOW_FREERATIO);//創(chuàng)建了一個新窗口,參數(shù)1表示名稱,第二個參數(shù)代表一個自由的比例imshow("雙邊模糊", dst);//表示顯示在新創(chuàng)建的 }29 實時視頻人臉檢測
OpenCV4.x中基于深度神經(jīng)網(wǎng)絡(luò)模型的高實時,穩(wěn)定的人臉檢測演示。
dnn::Net net = dnn::readNetFromTensorflow(root_dir+ "opencv_face_detector_uint8.pb", root_dir+"opencv_face_detector.pbtxt"); VideoCapture capture("D:/images/video/example_dsh.mp4"); Mat frame; while (true) {capture.read(frame);if (frame.empty()) {break;}Mat blob = dnn::blobFromImage(frame, 1.0, Size(300, 300), Scalar(104, 177, 123), false, false);net.setInput(blob);// NCHWMat probs = net.forward(); // Mat detectionMat(probs.size[2], probs.size[3], CV_32F, probs.ptr<float>());// 解析結(jié)果for (int i = 0; i < detectionMat.rows; i++) {float confidence = detectionMat.at<float>(i, 2);if (confidence > 0.5) {int x1 = static_cast<int>(detectionMat.at<float>(i, 3)*frame.cols);int y1 = static_cast<int>(detectionMat.at<float>(i, 4)*frame.rows);int x2 = static_cast<int>(detectionMat.at<float>(i, 5)*frame.cols);int y2 = static_cast<int>(detectionMat.at<float>(i, 6)*frame.rows);Rect box(x1, y1, x2 - x1, y2 - y1);rectangle(frame, box, Scalar(0, 0, 255), 2, 8, 0);}}imshow("人臉檢測演示", frame);int c = waitKey(1);if (c == 27) { // 退出break;} }本文僅做學(xué)術(shù)分享,如有侵權(quán),請聯(lián)系刪文。
下載1
在「3D視覺工坊」公眾號后臺回復(fù):3D視覺,即可下載 3D視覺相關(guān)資料干貨,涉及相機(jī)標(biāo)定、三維重建、立體視覺、SLAM、深度學(xué)習(xí)、點云后處理、多視圖幾何等方向。
下載2
在「3D視覺工坊」公眾號后臺回復(fù):3D視覺github資源匯總,即可下載包括結(jié)構(gòu)光、標(biāo)定源碼、缺陷檢測源碼、深度估計與深度補(bǔ)全源碼、點云處理相關(guān)源碼、立體匹配源碼、單目、雙目3D檢測、基于點云的3D檢測、6D姿態(tài)估計源碼匯總等。
下載3
在「3D視覺工坊」公眾號后臺回復(fù):相機(jī)標(biāo)定,即可下載獨(dú)家相機(jī)標(biāo)定學(xué)習(xí)課件與視頻網(wǎng)址;后臺回復(fù):立體匹配,即可下載獨(dú)家立體匹配學(xué)習(xí)課件與視頻網(wǎng)址。
重磅!3DCVer-學(xué)術(shù)論文寫作投稿?交流群已成立
掃碼添加小助手微信,可申請加入3D視覺工坊-學(xué)術(shù)論文寫作與投稿?微信交流群,旨在交流頂會、頂刊、SCI、EI等寫作與投稿事宜。
同時也可申請加入我們的細(xì)分方向交流群,目前主要有3D視覺、CV&深度學(xué)習(xí)、SLAM、三維重建、點云后處理、自動駕駛、多傳感器融合、CV入門、三維測量、VR/AR、3D人臉識別、醫(yī)療影像、缺陷檢測、行人重識別、目標(biāo)跟蹤、視覺產(chǎn)品落地、視覺競賽、車牌識別、硬件選型、學(xué)術(shù)交流、求職交流、ORB-SLAM系列源碼交流、深度估計等微信群。
一定要備注:研究方向+學(xué)校/公司+昵稱,例如:”3D視覺?+ 上海交大 + 靜靜“。請按照格式備注,可快速被通過且邀請進(jìn)群。原創(chuàng)投稿也請聯(lián)系。
▲長按加微信群或投稿
▲長按關(guān)注公眾號
3D視覺從入門到精通知識星球:針對3D視覺領(lǐng)域的視頻課程(三維重建系列、三維點云系列、結(jié)構(gòu)光系列、手眼標(biāo)定、相機(jī)標(biāo)定、orb-slam3等視頻課程)、知識點匯總、入門進(jìn)階學(xué)習(xí)路線、最新paper分享、疑問解答五個方面進(jìn)行深耕,更有各類大廠的算法工程人員進(jìn)行技術(shù)指導(dǎo)。與此同時,星球?qū)⒙?lián)合知名企業(yè)發(fā)布3D視覺相關(guān)算法開發(fā)崗位以及項目對接信息,打造成集技術(shù)與就業(yè)為一體的鐵桿粉絲聚集區(qū),近2000星球成員為創(chuàng)造更好的AI世界共同進(jìn)步,知識星球入口:
學(xué)習(xí)3D視覺核心技術(shù),掃描查看介紹,3天內(nèi)無條件退款
?圈里有高質(zhì)量教程資料、可答疑解惑、助你高效解決問題
覺得有用,麻煩給個贊和在看~??
總結(jié)
以上是生活随笔為你收集整理的实践教程 | 万字长文,值得收藏/参考的OpenCV C++基础代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 移动端IOS自动化测试框架搭建-无坑
- 下一篇: QTreeView QTreeWidge