Opencv中提取影象中的輪廓及中心點
阿新 • • 發佈:2019-02-16
// contourStudy.cpp : 定義控制檯應用程式的入口點。
//本文所提取的輪廓具有的特徵: 只有一個無孔洞的內連通
#include "stdafx.h" #include <opencv2/opencv.hpp> #include <iostream> #include <stack> using namespace std; #include <cv.h> #include <highgui.h> //計算輪廓深度 int GetLayerCnt(CvSeq *seq) { int count = 0; while (seq->v_next) { count++; seq = seq->v_next; } return count; } //獲取只有一個內連通的輪廓 void GetAllContourByLimit(CvSeq *contour, vector<CvSeq *> &vecSeq) { int count = 0, count2 = 0; CvSeq *contourNoLevel = 0, *contourSameLevel = 0; stack<CvSeq *> data; CvSeq *node = 0, *tmpContour = 0; data.push(contour); while (!data.empty()) { node = data.top(); data.pop(); tmpContour = node->h_next; //brother if (tmpContour) { data.push(tmpContour); } //child count = GetLayerCnt(node); if (count >= 2)// 若要獲取 深度為n 的內輪廓,則 count >= n+1 . { contourNoLevel = node->v_next->v_next;// 此處參照count的值 if (!contourNoLevel->v_next && !contourNoLevel->h_next) { vecSeq.push_back(node); } if (contourNoLevel->h_next || contourNoLevel->v_next) { data.push(contourNoLevel); } } else if (count == 1) { tmpContour = node->v_next->h_next; if (tmpContour) { data.push(tmpContour); } } } } //抓取輪廓中心 void GetContourCenter(CvSeq *contour, CvPoint &p) { //重心法抓中心點 int contourlength = contour->total; CvPoint *pt = 0; double avg_px = 0, avg_py = 0; for (int i = 0; i < contourlength; i++) { pt = CV_GET_SEQ_ELEM(CvPoint, contour, i); avg_px += pt->x; avg_py += pt->y; } p.x = avg_px / contourlength; p.y = avg_py / contourlength; } //主函式 int _tmain(int argc, _TCHAR* argv[]) { IplImage* src; // the first command line parameter must be file name of binary (black-n-white) image if ((src = cvLoadImage("7.bmp", 0)) != NULL) { IplImage* dst = cvCreateImage(cvGetSize(src), 8, 3); CvMemStorage* storage = cvCreateMemStorage(0); CvSeq* contour = 0, *contourNoLevel = 0, *contourSameLevel = 0, *outpput = 0; cvThreshold(src, src, 1, 255, CV_THRESH_OTSU); cvNot(src, src); cvFindContours(src, storage, &contour, sizeof(CvContour), 3, CV_CHAIN_APPROX_NONE); cvZero(dst); vector<CvSeq *> vecSeq; vecSeq.clear(); //獲取所有隻有一個內連通的輪廓 GetAllContourByLimit(contour, vecSeq); //顯示 CvPoint pt; for (int i = 0; i<vecSeq.size(); i++) { if (1)//此處可以新增限制條件 { GetContourCenter(vecSeq[i]->v_next->next, pt); cvCircle(dst, pt, 2, cvScalar(0, 255, 0), 1, 8, 0); cvDrawContours(dst, vecSeq[i], CV_RGB(255, 0, 0), CV_RGB(0, 0, 0), -1, 2); } } cvNamedWindow("Result"); cvShowImage("Result", dst); cvWaitKey(0); } system("pause"); return 0; } //效果圖