opencv之圖像輪廓提取

進行輪廓提取時要將原圖二值化,因爲除了圖像的輪廓外其餘的都是無用的信息,以減少運算量

所用函數基礎介紹:

CvMemStorage

  1. CvMemStorage   
  2. typedef struct CvMemStorage   
  3. {   
  4. struct CvMemBlock* bottom;/* first allocated block */   
  5. struct CvMemBlock* top; /* the current memory block - top of the stack */   
  6. struct CvMemStorage* parent; /* borrows new blocks from */   
  7. int block_size; /* block size */   
  8. int free_space; /* free space in the top block (in bytes) */   
  9. } CvMemStorage;   
內存存儲器是一個可用來存儲諸如序列,輪廓,圖形,子劃分等動態增長數據結構的底層結構。它是由一系列以同等大小的內存塊構成,呈列表型 ---bottom 域指的是列首,top 域指的是當前指向的塊但未必是列尾.在bottom和top之間所有的塊(包括bottom, 不包括top)被完全佔據了空間;在 top和列尾之間所有的塊(包括塊尾,不包括top)則是空的;而top塊本身則被佔據了部分空間 -- free_space 指的是top塊剩餘的空字節數。新分配的內存緩衝區(或顯示的通過 cvMemStorageAlloc 函數分配,或隱示的通過 cvSeqPush, cvGraphAddEdge等高級函數分配)總是起始於當前塊(即top塊)的剩餘那部分,如果剩餘那部分能滿足要求(夠分配的大小)。分配後,free_space 就減少了新分配的那部分內存大小,外加一些用來保存適當列型的附加大小。當top塊的剩餘空間無法滿足被分配的塊(緩衝區)大小時,top塊的下一個存儲塊被置爲當前塊(新的top塊) -- free_space 被置爲先前分配的整個塊的大小。如果已經不存在空的存儲塊(即:top塊已是列尾),則必須再分配一個新的塊(或從parent那繼承,見 cvCreateChildMemStorage)並將該塊加到列尾上去。於是,存儲器(memory storage)就如同棧(Stack)那樣, bottom指向棧底,(top, free_space)對指向棧頂。棧頂可通過 cvSaveMemStoragePos保存,通過 cvRestoreMemStoragePos 恢復指向, 通過 cvClearStorage 重置。 
cvCreateMemStorage 
創建內存塊 
  1. CvMemStorage* cvCreateMemStorage( int block_size=0 );   
block_size:存儲塊的大小以字節表示。如果大小是 0 byte, 則將該塊設置成默認值 當前默認大小爲64k. 
函數 cvCreateMemStorage 創建一內存塊並返回指向塊首的指針。起初,存儲塊是空的。頭部(即:header)的所有域值都爲 0,除了 block_size 外.

cvReleaseMemStorage 
釋放內存塊 

  1. void cvReleaseMemStorage( CvMemStorage** storage );   

CvSeq* cvCreateSeq(int seq_flags,int header_size,int elem_size,CvMemStorage* storage)
功能:創建一序列
說明:CvSeq本身就是一個可增長的序列,不是固定的序列

cvThreshold:

作用:函數 cvThreshold 對單通道數組應用固定閾值操作。該函數的典型應用是對灰度圖像進行閾值操作得到二值圖像。(cvCmpS 也可以達到此目的) 或者是去掉噪聲,例如過濾很小或很大象素值的圖像點。本函數支持的對圖像取閾值的方法由 threshold_type 確定。

  形式:void cvThreshold( const CvArr* src, CvArr* dst, double threshold, double max_value, int threshold_type );

  src:原始數組 (單通道 , 8-bit of 32-bit 浮點數)。dst:輸出數組,必須與 src 的類型一致,或者爲 8-bit。

  threshold:閾值

  max_value:使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值。

  threshold_type:閾值類型 threshold_type=CV_THRESH_BINARY:

  如果 src(x,y)>threshold 0,dst(x,y) = max_value, 否則.

  threshold_type=CV_THRESH_BINARY_INV:

  如果 src(x,y)>threshold,dst(x,y) = 0; 否則,dst(x,y) = max_value.

  threshold_typ

 

本函數支持的對圖像取閾值的方法由 threshold_type 確定:

threshold_type=CV_THRESH_BINARY:

dst(x,y) = max_value, if src(x,y)>threshold 0, otherwise.

threshold_type=CV_THRESH_BINARY_INV:

dst(x,y) = 0, if src(x,y)>threshold; dst(x,y) = max_value, otherwise.

threshold_type=CV_THRESH_TRUNC:

dst(x,y) = threshold, if src(x,y)>threshold;   dst(x,y) = src(x,y), otherwise.

threshold_type=CV_THRESH_TOZERO:

dst(x,y) = src(x,y), if (x,y)>threshold ;  dst(x,y) = 0, otherwise.

threshold_type=CV_THRESH_TOZERO_INV:

dst(x,y) = 0, if src(x,y)>threshold ;  dst(x,y) = src(x,y), otherwise.


源代碼:

#include <iostream>

#include "cv.h"
       #include "cxcore.h"

#include "highgui.h"
using namespace std;
int main()
{
CvMemStorage *storage = cvCreateMemStorage(0);   // 內存存儲序列
IplImage *img = cvLoadImage("F:\\bb2.jpg", 0);
IplImage *imgColor = cvCreateImage(cvGetSize(img), 8, 3);
IplImage *contoursImage = cvCreateImage(cvGetSize(img), 8, 1);


CvSeq *contours = 0, *contoursTemp = 0;  //OPENCV中的一種數據結構,類似於數組
cvZero(contoursImage);
cvThreshold(img, img, 100, 255, CV_THRESH_BINARY);  // 二值化操作,原圖已經變爲灰度圖
cvCvtColor(img, imgColor, CV_GRAY2BGR);
int totals = cvFindContours(img, storage,&contours, sizeof(CvContour),    //img必須是一個二值圖像 storage 用來存儲的contours指向存儲的第一個輪廓
CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, cvPoint(0,0));
contoursTemp = contours;
int count = 0;
int i;
for(;contoursTemp != 0; contoursTemp = contoursTemp -> h_next)  /// 這樣可以訪問每一個輪廓  ====橫向輪廓
{
for(i = 0; i < contoursTemp -> total; i++)    // 提取一個輪廓的所有座標點
{
CvPoint *pt = (CvPoint*) cvGetSeqElem(contoursTemp, i);   // 得到一個輪廓中一個點的函數cvGetSeqElem
cvSetReal2D(contoursImage, pt->y, pt->x, 255.0);
cvSet2D(imgColor, pt->y, pt->x, cvScalar(0,0,255,0));
}
count ++;
CvSeq *InterCon = contoursTemp->v_next;     // 訪問每個輪廓的縱向輪廓
for(; InterCon != 0; InterCon = InterCon ->h_next)
{
for(i = 0; i < InterCon->total; i++ )


{
CvPoint *pt = (CvPoint*)cvGetSeqElem(InterCon, i);
cvSetReal2D(contoursImage, pt->y, pt->x, 255.0);
cvSet2D(imgColor, pt->y, pt->x, cvScalar(0, 255, 0, 0));
}
}
}
cvNamedWindow("contoursImage");
cvShowImage("contoursImage", contoursImage);
cvNamedWindow("imgColor");
cvShowImage("imgColor",imgColor);
cvWaitKey(0);
cvReleaseMemStorage(&storage);      // 也要釋放內存序列空間
cvReleaseImage(&contoursImage);
cvReleaseImage(&imgColor);
cvDestroyWindow("contoursImage");
cvDestroyWindow("imgColor");
return 0;
}







發佈了8 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章