1. 程式人生 > >我的OpenCV學習筆記(20):提取元素的輪廓及形狀描述子

我的OpenCV學習筆記(20):提取元素的輪廓及形狀描述子

先看提取輪廓的程式碼:

	Mat image = imread("D:/picture/images/binaryGroup.bmp",0);
	if(!image.data)
		return -1;
	imshow("源影象",image);

	//獲取輪廓
	std::vector<std::vector<Point>> contours;
	//獲取輪廓:
	findContours(image,			//影象
		contours,				//輪廓點
						//包含影象拓撲結構的資訊(可選引數,這裡沒有選)
		CV_RETR_EXTERNAL,			//獲取輪廓的方法(這裡獲取外圍輪廓)
		CV_CHAIN_APPROX_NONE);		//輪廓近似的方法(這裡不近似,獲取全部輪廓)
	//列印輪廓資訊
	std::cout<<"共有外圍輪廓:"<<contours.size()<<"條"<<std::endl;
	std::vector<std::vector<Point>>::const_iterator itContours = contours.begin();
	for(;itContours != contours.end();++itContours)
	{
		std::cout<<"每個輪廓的長度: "<<itContours->size()<<std::endl;
	}

注意到輪廓的儲存格式為std::vector<std::vector<Point>>,他說明整個輪廓是若干條輪廓按一定順序組成的,而每個輪廓中的點也是有順序的。

畫出輪廓就比較簡單了:

	//畫出輪廓
	Mat result(image.size(),CV_8U,Scalar(255));
	//畫出輪廓,引數為:畫板,輪廓,輪廓指示(這裡畫出所有輪廓),顏色,線粗
	drawContours(result,contours,-1,Scalar(0),2);
	imshow("提取外圍輪廓",result);

還要注意提取輪廓的方法還有很多種,比如CV_RETR_LIST代表所有輪廓

	findContours(image,			//影象
		contours,				//輪廓點
						//包含影象拓撲結構的資訊(可選引數,這裡沒有選)
		CV_RETR_LIST,			//獲取輪廓的方法(這裡獲取所有輪廓)
		CV_CHAIN_APPROX_NONE);		//輪廓近似的方法(這裡不近似,獲取全部輪廓
	//畫出輪廓
	drawContours(result,contours,-1,Scalar(0),2);
	imshow("提取所有輪廓",result);

通常,這樣提取的輪廓包含一些我們不希望的輪廓(比如一些小洞),或者假如我們知道我們感興趣的物體輪廓的大概範圍時,我們就可以用下面的辦法縮小目標範圍:

	//除去太長或者太短的輪廓
	int cmin = 100;
	int cmax = 1000;
	std::vector<std::vector<Point>>::const_iterator itc = contours.begin();
	while(itc != contours.end())
	{
		if(itc->size() < cmin || itc->size() > cmax)
			itc = contours.erase(itc);
		else
			++itc;
	}
	
	//把結果畫在源影象上:
	Mat original = imread("D:/picture/images/group.jpg");
	if(!original.data)
		return -1;
	drawContours(original,contours,-1,Scalar(255,255,255),2);
	imshow("動物的輪廓",original);

	//將輪廓重繪於白板上
	result.setTo(Scalar(255));
	drawContours(result,contours,-1,Scalar(0),1);


怎麼提取輪廓的特徵呢?OpenCV提供了很多函式,我們展示其中的幾個:

	//輪廓的形狀描述子
	//外接矩形
	Rect r0 = boundingRect(Mat(contours[0]));
	rectangle(result,r0,Scalar(0),2);

	//最小外接圓
	float radius;
	Point2f center;
	minEnclosingCircle(Mat(contours[1]),center,radius);
	circle(result,Point(center),static_cast<int>(radius),Scalar(0),2);

	//多邊形估計
	std::vector<Point> poly;
	//引數為:輸入影象的2維點集,輸出結果,估計精度,是否閉合
	approxPolyDP(Mat(contours[2]),poly,5,true);
	std::cout<<"多邊形大小:"<<poly.size()<<std::endl;
	//畫出結果
	std::vector<Point>::const_iterator itp = poly.begin();
	while(itp != poly.end()-1)
	{
		line(result,*itp,*(itp+1),Scalar(0),2);
		++itp;
	}
	//將第一個點和最後一點連起來
	line(result,*(poly.begin()),*(poly.end()-1),Scalar(128),2);


	//計算凸包
	std::vector<Point> hull;
	convexHull(Mat(contours[3]),hull);
	std::vector<cv::Point>::const_iterator it= hull.begin();
	while(it != (hull.end()-1))
	{
		line(result,*it,*(it+1),Scalar(0),2);
		++it;
	}
	line(result,*(hull.begin()),*(hull.end()-1),Scalar(0),2);
	

	//計算矩資訊
	itc = contours.begin();
	while(itc != contours.end())
	{
		//計算所有的距
		Moments mom = moments(Mat(*itc++));
		//計算並畫出質心
		circle(result,Point(mom.m10/mom.m00,mom.m01/mom.m00),2,Scalar(2),2);
	}
	imshow("形狀描述子",result);

我們再次看到,輪廓的確是有順序的。值得注意的是矩資訊:OpenCV提供了一個結構體Moments,它的元素就是計算好的矩資訊,裡面存放了常用的距。

其實,OpenCV還提供了許多其他的形狀描述子,比如函式cv::minAreaRect計算了最小外界傾斜的矩形。函式cv::contourArea估計輪廓區域的面積(裡面的畫素數)。函式cv::pointPolygonTest計算一個點是否在輪廓內,cv::matchShapes測量了2兩個輪廓的相似程度等等。這裡就不一一介紹了。

相關推薦

OpenCV學習筆記20提取元素輪廓形狀描述

先看提取輪廓的程式碼: Mat image = imread("D:/picture/images/binaryGroup.bmp",0); if(!image.data) return -1; imshow("源影象",image); //獲取輪廓 std

OpenCV學習筆記操作每個畫素

首先推薦一本書:《OpenCV 2 Computer Vision Application Programming Cookbook》網上可以下載到這本書的英文版,貌似沒有翻譯的。這本書的特點是裡面的程式不是那種為了演示函式功能而寫的面向過程的小程式,而是用面向物件的思路寫

opencv學習筆記幾種去噪濾波器的實現

現在在上數字影象處理的課程,最近的一次作業要求不用OpenCV自帶的濾波器函式來實現幾種濾波器,以實現對加入椒鹽噪聲的影象的去噪。也是對markdown編輯器的一次練習。 椒鹽噪聲 椒鹽噪聲是一種很簡單的噪聲,即隨機將影象中一定數量的畫素點設定為0(黑)

Python3+OpenCV學習筆記影象濾波基礎均值、高斯、中值、雙邊

OpenCV中還可以在影象上進行繪圖操作,由於資料都比較完善,所以附上鍊接,自行參悟。 好了,進入正題。在一張影象,在資料儲存或傳輸的過程中,或多或少都會引入噪聲,常見的影象噪聲如高斯噪聲、瑞利噪聲、椒鹽噪聲等,可參加連結:數字影象噪聲 為了避免噪聲對影象資訊進行干擾或

OpenCV學習筆記計算影象直方圖

畫素值在影象中的分佈情況是這幅影象的一個重要特徵。直方圖是一個簡單的表,它給出了衣服影象或一組影象中擁有給定數值的畫素數量。在OpenCV中計算直方圖可以通過使用cv::clacHist()函式。這是一

OpenCV學習筆記SVM+HOG實現的行人檢測

因為一個專案的需求接觸到OpenCV裡的SVM和HOG特徵演算法,根據網上的教程一個部落格,給自己準備了一個關於行人檢測demo,裡面也有一些程式碼也是參考網上的demo,這裡大致記錄下demo的程式碼和自己的遇到的一些小問題。 參考部落格/文章: HOG+SVM行人檢測 目標檢測的影象特徵

OpenCV學習筆記OpenCV報錯“libpng error: IDAT: invalid distance too far back”

    這一陣子在學習用OpenCV的SVM+HOG進行行人捕捉,在學習網上原始碼的時候使用了OpenCV官方的訓練資料集,cv2的庫在read訓練資料的時候,有那麼幾個資料夾裡面的照片是沒辦法直接讀取,會報錯“libpng error: IDAT: invalid distan

OpenCV學習筆記14形態學濾波對影象進行邊緣角點檢測

</pre><pre name="code" class="cpp">#include "stdafx.h" #include<opencv2/opencv.hpp> using namespace cv; class MorphoFe

OpenCV學習筆記09opencv3.2+cmake3.8+VS2013,編譯opencv_contrib

Cmake編譯opencv contrib部分 1. 前言 最近才知道,在OpenCV3.0 之後,OpenCV演算法包被拆分成兩部分,官方釋出的OpenCV包只包含最基礎最穩定的部分,而某些影象處理的經典演算法如SIFT和SURF等被封裝到opencv_contrib中。如果想

OpenCV學習筆記04Mat類詳解

1. 前言:Mat類簡介 OpenCV 作為強大的計算機視覺開源庫,很大程度上參考了MatLab的實現細節和語法風格,比如說,在OpenCV2.x版本以後,越來越多的函式實現了MatLab所具有的功能,甚至乾脆連函式名都一模一樣(如 imre

python OpenCV學習筆記圖片的幾何變形

縮放 import numpy as np import cv2 as cv img = cv.imread('test.jpg') res = cv.resize(img, None, fx=2, fy=2, interpolation=

OpenCV學習筆記10人臉檢測

1. 前言 OpenCV實現人臉檢測主要是採用了adaboost分類演算法,這種演算法是屬於機器學習範疇,需要使用海量圖片進行訓練,得到一個分類檔案,然後根據該檔案中的引數進行人臉檢測。由於訓練過程比較複雜,我們在此不再累述,直接使用官方釋出的XML檔案即可。

OpenCV學習筆記使用CascadeClassifier檢測人臉

#include "stdafx.h" #include <opencv2/opencv.hpp> class FaceRecognition { private: cv::Mat m_mImg; char* face_cascade_name = "D:\\OpenCV\\opencv\

OpenCV學習筆記OpenCV使用imwrite儲存4通道圖片僅對png有效

轉載OpenCV官方文件中imwrite函式的說明,如何儲存4通道的影象。 轉載地址 https://www.docs.opencv.org/2.4.13/modules/highgui/doc/reading_and_writing_images_and_video.h

openCV學習筆記7cvRectangle與cv::rectangle的用法

在第一次使用cvRectangle繪製矩形的時候遇到一個問題:Error:不存在從“cv::Mat”到"CvArr*"的適當轉換函式,就特意查了查資料,總結如下。 cvRentangle和cv::rectangle函式原型對比: C:       void cvRectan

OpenCV學習筆記11libfacedetection人臉檢測的配置與使用

1. 前言 libfacedetection庫是深圳大學的於仕琪老師釋出的開源人臉檢測庫,相比於OpenCV自帶的CascadeClassifier人臉檢測,無論在速度上還是精度上,都有巨大的優勢,是目前已知開源庫中最好用的一款。 本文通過學習libface

Python3+OpenCV學習筆記影象載入、顯示和儲存

img = cv2.imread('Rachel.jpg')載入影象後,當然需要顯示出來,我們才能看到,所以,接下來用到第二個函式cv2.imshow(windowname, filename)“windowname”輸入顯示視窗的名稱,引數型別str,需要開啟多個視窗時,只需要“windowname”不同

Spring學習筆記Spring JDBC 框架應用示例

JDBC 框架概述 在使用普通的 JDBC 資料庫時,就會很麻煩的寫不必要的程式碼來處理異常,開啟和關閉資料庫連線等。但 Spring JDBC 框架負責所有的低層細節,從開始開啟連線,準備和執行 SQL 語句,處理異常,處理事務,到最後關閉連線。 所以當從資料庫中獲取資

Unity3D學習筆記元素和書籍推薦

col 所有 sele super project ons 描述 直觀 gen 書籍推薦: 3D數學基礎:圖形與遊戲開發——遊戲軟件開發專家系列(美)鄧恩 Unity Shader入門精要 馮樂樂(92年) 數據結構(Python語言描述) 數據結構、算法與應用(C++語

安卓學習筆記——執行緒的用法怎樣在執行緒中更新UI

建立執行緒方法: 1、新建一個繼承自Thread的類MyThread,然後重寫父類的run()方法,在裡面寫要執行的內容; class MyThread extends Thread { @Ove