OpenCV之imgproc 模块. 图像处理(5)在图像中寻找轮廓 计算物体的凸包 创建包围轮廓的矩形和圆形边界框 为轮廓创建可倾斜的边界框和椭圆 轮廓矩 多边形测试
生活随笔
收集整理的這篇文章主要介紹了
OpenCV之imgproc 模块. 图像处理(5)在图像中寻找轮廓 计算物体的凸包 创建包围轮廓的矩形和圆形边界框 为轮廓创建可倾斜的边界框和椭圆 轮廓矩 多边形测试
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
在圖像中尋找輪廓
目標(biāo)
在這個教程中你將學(xué)到如何:
- 使用OpenCV函數(shù)?findContours
- 使用OpenCV函數(shù)?drawContours
原理
例程
教程的代碼在下面給出. 你也可以從?這里?下載
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h>using namespace cv; using namespace std;Mat src; Mat src_gray; int thresh = 100; int max_thresh = 255; RNG rng(12345);/// Function header void thresh_callback(int, void* );/** @function main */ int main( int argc, char** argv ) {/// 加載源圖像src = imread( argv[1], 1 );/// 轉(zhuǎn)成灰度并模糊化降噪cvtColor( src, src_gray, CV_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );/// 創(chuàng)建窗體char* source_window = "Source";namedWindow( source_window, CV_WINDOW_AUTOSIZE );imshow( source_window, src );createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );thresh_callback( 0, 0 );waitKey(0);return(0); }/** @function thresh_callback */ void thresh_callback(int, void* ) {Mat canny_output;vector<vector<Point> > contours;vector<Vec4i> hierarchy;/// 用Canny算子檢測邊緣Canny( src_gray, canny_output, thresh, thresh*2, 3 );/// 尋找輪廓findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );/// 繪出輪廓Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );for( int i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );}/// 在窗體中顯示結(jié)果namedWindow( "Contours", CV_WINDOW_AUTOSIZE );imshow( "Contours", drawing ); }例程說明?
結(jié)果
原圖和檢測到的輪廓如下:
|
|
|
計(jì)算物體的凸包
目標(biāo)
在這個教程中你將學(xué)習(xí)到如何:
- 使用OpenCV函數(shù)?convexHull
原理
例程
教程的代碼在下面給出. 你也可以從?這里?下載
#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>#include <stdio.h>#include <stdlib.h>using namespace cv;using namespace std;Mat src; Mat src_gray;int thresh = 100;int max_thresh = 255;RNG rng(12345);/// Function headervoid thresh_callback(int, void* );/** @function main */ int main( int argc, char** argv ){/// 加載源圖像src = imread( argv[1], 1 );/// 轉(zhuǎn)成灰度圖并進(jìn)行模糊降噪cvtColor( src, src_gray, CV_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );/// 創(chuàng)建窗體char* source_window = "Source";namedWindow( source_window, CV_WINDOW_AUTOSIZE );imshow( source_window, src );createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback );thresh_callback( 0, 0 );waitKey(0);return(0);}/** @function thresh_callback */void thresh_callback(int, void* ){Mat src_copy = src.clone();Mat threshold_output;vector<vector<Point> > contours;vector<Vec4i> hierarchy;/// 對圖像進(jìn)行二值化threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );/// 尋找輪廓findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );/// 對每個輪廓計(jì)算其凸包vector<vector<Point> >hull( contours.size() );for( int i = 0; i < contours.size(); i++ ){ convexHull( Mat(contours[i]), hull[i], false ); }/// 繪出輪廓及其凸包Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );for( int i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );drawContours( drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point() );}/// 把結(jié)果顯示在窗體namedWindow( "Hull demo", CV_WINDOW_AUTOSIZE );imshow( "Hull demo", drawing );}例程說明
結(jié)果
原圖和結(jié)果圖如下:
|
|
|
創(chuàng)建包圍輪廓的矩形和圓形邊界框
目標(biāo)
在這節(jié)教程中您將學(xué)到:
- 使用OpenCV函數(shù)?boundingRect?來計(jì)算包圍輪廓的矩形框.
- 使用OpenCV函數(shù)?minEnclosingCircle?來計(jì)算完全包圍已有輪廓最小圓.
原理
代碼
下面是本節(jié)教程源碼. 你也可以從?這里?下載.
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h>using namespace cv; using namespace std;Mat src; Mat src_gray; int thresh = 100; int max_thresh = 255; RNG rng(12345);/// 函數(shù)聲明 void thresh_callback(int, void* );/** @主函數(shù) */ int main( int argc, char** argv ) {/// 載入原圖像, 返回3通道圖像src = imread( argv[1], 1 );/// 轉(zhuǎn)化成灰度圖像并進(jìn)行平滑cvtColor( src, src_gray, CV_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );/// 創(chuàng)建窗口char* source_window = "Source";namedWindow( source_window, CV_WINDOW_AUTOSIZE );imshow( source_window, src );createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback );thresh_callback( 0, 0 );waitKey(0);return(0); }/** @thresh_callback 函數(shù) */ void thresh_callback(int, void* ) {Mat threshold_output;vector<vector<Point> > contours;vector<Vec4i> hierarchy;/// 使用Threshold檢測邊緣threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );/// 找到輪廓findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );/// 多邊形逼近輪廓 + 獲取矩形和圓形邊界框vector<vector<Point> > contours_poly( contours.size() );vector<Rect> boundRect( contours.size() );vector<Point2f>center( contours.size() );vector<float>radius( contours.size() );for( int i = 0; i < contours.size(); i++ ){ approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );boundRect[i] = boundingRect( Mat(contours_poly[i]) );minEnclosingCircle( contours_poly[i], center[i], radius[i] );}/// 畫多邊形輪廓 + 包圍的矩形框 + 圓形框Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );for( int i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );drawContours( drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point() );rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 );}/// 顯示在一個窗口namedWindow( "Contours", CV_WINDOW_AUTOSIZE );imshow( "Contours", drawing ); }代碼說明
結(jié)果
如下所示:
|
|
|
為輪廓創(chuàng)建可傾斜的邊界框和橢圓
目標(biāo)
在這個教程中你將學(xué)習(xí)到如何:
- 使用OpenCV函數(shù)?minAreaRect
- 使用OpenCV函數(shù)?fitEllipse
原理
例程
例程的代碼在下面顯示. 你也可以從?這里?下載
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h>using namespace cv; using namespace std;Mat src; Mat src_gray; int thresh = 100; int max_thresh = 255; RNG rng(12345);/// Function header void thresh_callback(int, void* );/** @function main */ int main( int argc, char** argv ) {/// 加載源圖像src = imread( argv[1], 1 );/// 轉(zhuǎn)為灰度圖并模糊化cvtColor( src, src_gray, CV_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );/// 創(chuàng)建窗體char* source_window = "Source";namedWindow( source_window, CV_WINDOW_AUTOSIZE );imshow( source_window, src );createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback );thresh_callback( 0, 0 );waitKey(0);return(0); }/** @function thresh_callback */ void thresh_callback(int, void* ) {Mat threshold_output;vector<vector<Point> > contours;vector<Vec4i> hierarchy;/// 閾值化檢測邊界threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );/// 尋找輪廓findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );/// 對每個找到的輪廓創(chuàng)建可傾斜的邊界框和橢圓vector<RotatedRect> minRect( contours.size() );vector<RotatedRect> minEllipse( contours.size() );for( int i = 0; i < contours.size(); i++ ){ minRect[i] = minAreaRect( Mat(contours[i]) );if( contours[i].size() > 5 ){ minEllipse[i] = fitEllipse( Mat(contours[i]) ); }}/// 繪出輪廓及其可傾斜的邊界框和邊界橢圓Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );for( int i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );// contourdrawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );// ellipseellipse( drawing, minEllipse[i], color, 2, 8 );// rotated rectanglePoint2f rect_points[4]; minRect[i].points( rect_points );for( int j = 0; j < 4; j++ )line( drawing, rect_points[j], rect_points[(j+1)%4], color, 1, 8 );}/// 結(jié)果在窗體中顯示namedWindow( "Contours", CV_WINDOW_AUTOSIZE );imshow( "Contours", drawing ); }說明
結(jié)果
結(jié)果如下圖:
|
|
|
輪廓矩
目標(biāo)
在這節(jié)教程中您將學(xué)到:
- 使用OpenCV函數(shù)?moments?計(jì)算圖像所有的矩(最高到3階)
- 使用OpenCV函數(shù)?contourArea?來計(jì)算輪廓面積
- 使用OpenCV函數(shù)?arcLength?來計(jì)算輪廓或曲線長度
原理
代碼
下面是本節(jié)教程源碼. 你也可以從?這里?下載.
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h>using namespace cv; using namespace std;Mat src; Mat src_gray; int thresh = 100; int max_thresh = 255; RNG rng(12345);/// 函數(shù)聲明 void thresh_callback(int, void* );/** @主函數(shù) */ int main( int argc, char** argv ) {/// 讀入原圖像, 返回3通道圖像數(shù)據(jù)src = imread( argv[1], 1 );/// 把原圖像轉(zhuǎn)化成灰度圖像并進(jìn)行平滑cvtColor( src, src_gray, CV_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );/// 創(chuàng)建新窗口char* source_window = "Source";namedWindow( source_window, CV_WINDOW_AUTOSIZE );imshow( source_window, src );createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );thresh_callback( 0, 0 );waitKey(0);return(0); }/** @thresh_callback 函數(shù) */ void thresh_callback(int, void* ) {Mat canny_output;vector<vector<Point> > contours;vector<Vec4i> hierarchy;/// 使用Canndy檢測邊緣Canny( src_gray, canny_output, thresh, thresh*2, 3 );/// 找到輪廓findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );/// 計(jì)算矩vector<Moments> mu(contours.size() );for( int i = 0; i < contours.size(); i++ ){ mu[i] = moments( contours[i], false ); }/// 計(jì)算中心矩:vector<Point2f> mc( contours.size() );for( int i = 0; i < contours.size(); i++ ){ mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); }/// 繪制輪廓Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );for( int i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );circle( drawing, mc[i], 4, color, -1, 8, 0 );}/// 顯示到窗口中namedWindow( "Contours", CV_WINDOW_AUTOSIZE );imshow( "Contours", drawing );/// 通過m00計(jì)算輪廓面積并且和OpenCV函數(shù)比較printf("\t Info: Area and Contour Length \n");for( int i = 0; i< contours.size(); i++ ){printf(" * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f \n", i, mu[i].m00, contourArea(contours[i]), arcLength( contours[i], true ) );Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );circle( drawing, mc[i], 4, color, -1, 8, 0 );} }代碼說明
結(jié)果
如下所示:
|
|
|
|
多邊形測試
目的
本教程指導(dǎo)用戶:
- 使用OpenCV函數(shù)?pointPolygonTest
理論
代碼
本教程代碼如下所示. 用戶也可以點(diǎn)擊?這里下載
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h>using namespace cv; using namespace std;/** @function main */ int main( int argc, char** argv ) {/// 創(chuàng)建一個圖形 const int r = 100;Mat src = Mat::zeros( Size( 4*r, 4*r ), CV_8UC1 );/// 繪制一系列點(diǎn)創(chuàng)建一個輪廓:vector<Point2f> vert(6);vert[0] = Point( 1.5*r, 1.34*r );vert[1] = Point( 1*r, 2*r );vert[2] = Point( 1.5*r, 2.866*r );vert[3] = Point( 2.5*r, 2.866*r );vert[4] = Point( 3*r, 2*r );vert[5] = Point( 2.5*r, 1.34*r );/// 在src內(nèi)部繪制for( int j = 0; j < 6; j++ ){ line( src, vert[j], vert[(j+1)%6], Scalar( 255 ), 3, 8 ); }/// 得到輪廓vector<vector<Point> > contours; vector<Vec4i> hierarchy;Mat src_copy = src.clone();findContours( src_copy, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);/// 計(jì)算到輪廓的距離Mat raw_dist( src.size(), CV_32FC1 );for( int j = 0; j < src.rows; j++ ){ for( int i = 0; i < src.cols; i++ ){ raw_dist.at<float>(j,i) = pointPolygonTest( contours[0], Point2f(i,j), true ); }}double minVal; double maxVal;minMaxLoc( raw_dist, &minVal, &maxVal, 0, 0, Mat() );minVal = abs(minVal); maxVal = abs(maxVal);/// 圖形化的顯示距離Mat drawing = Mat::zeros( src.size(), CV_8UC3 );for( int j = 0; j < src.rows; j++ ){ for( int i = 0; i < src.cols; i++ ){if( raw_dist.at<float>(j,i) < 0 ){ drawing.at<Vec3b>(j,i)[0] = 255 - (int) abs(raw_dist.at<float>(j,i))*255/minVal; }else if( raw_dist.at<float>(j,i) > 0 ){ drawing.at<Vec3b>(j,i)[2] = 255 - (int) raw_dist.at<float>(j,i)*255/maxVal; }else{ drawing.at<Vec3b>(j,i)[0] = 255; drawing.at<Vec3b>(j,i)[1] = 255; drawing.at<Vec3b>(j,i)[2] = 255; }}}/// 創(chuàng)建窗口顯示結(jié)果char* source_window = "Source";namedWindow( source_window, CV_WINDOW_AUTOSIZE );imshow( source_window, src );namedWindow( "Distance", CV_WINDOW_AUTOSIZE );imshow( "Distance", drawing );waitKey(0);return(0); }解釋?
結(jié)果
輸出如下:
|
|
|
from: http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/table_of_content_imgproc/table_of_content_imgproc.html#table-of-content-imgproc
總結(jié)
以上是生活随笔為你收集整理的OpenCV之imgproc 模块. 图像处理(5)在图像中寻找轮廓 计算物体的凸包 创建包围轮廓的矩形和圆形边界框 为轮廓创建可倾斜的边界框和椭圆 轮廓矩 多边形测试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV之imgproc 模块. 图
- 下一篇: OpenCV之highgui 模块. 高