擷取目標對象中心

來源:互聯網
上載者:User
擷取目標對象中心




   目標對象中心不等同於連通地區中心,一個連通地區內可能包括多個粘連目標對象。擷取目標對象中心要比擷取連通地區中心更為複雜,因為需要解決粘連部分的分割問題。

  對二值圖進行距離變換後,目標對象中心處的像素值具備局部最大特性。換而言之,在距離映像中的局部最大值中包含了全部的中心點。對局部最大值點的定義為:對於任何一個非零點,如果其像素值不小於其8領域的像素值,則該點為局部最大值點。

  在局部最大值點中包含中心點和非中心點,如果能夠確定中心點和非中心點的判別依據,那麼就可以從中找出全部的中心點。在同一連通域中,任意兩個局部最大值點之間距離小於某個閾值時,其中像素值較小的一個局部最大值點為非中心點。該閾值由像素值較大的點乘上一個粘連繫數確定,粘連繫數通常取值為1附近的某個值。

  由於事先無法確定局部最大值點數量,無法事先分配合適的記憶體空間,因此可以使用vector來動態管理記憶體。另外一個比較麻煩的問題是將所有局部最大值點按連通地區進行分組,因為整個處理過程是針對同一連通地區的,而非整幅映像。按連通地區進行分組的方法很多,下面採用的方法是將每個連通地區進行編號,然後計算每個最大局部最大值點所在連通地區的編號,並按編號進行排序,即完成分組。


 

#include "cxcore.h"<br />#include "cv.h"<br />#pragma comment(lib, "cxcore.lib")<br />#pragma comment(lib, "cv.lib")<br />struct CenterPoint<br />{<br />int nObject;<br />float fDistance;<br />CvPoint2D32f ptCenter;<br />public:<br />bool operator < (const CenterPoint &center) const<br />{<br />return nObject < center.nObject;<br />}<br />};<br />typedef std::vector<CenterPoint> VCenter;<br />typedef std::vector<CenterPoint>::iterator CenterIter;<br />// 對象中心點<br />// 參數:<br />// 1. pBinary: 輸入二值映像,單通道,位深IPL_DEPTH_8U。<br />// 2. pDistance: 輸出距離映像,單通道,位深IPL_DEPTH_32F,與pBinary等大。<br />// 3. vecCenter: 返回對象中心點,可以預先分配足夠的記憶體,從而減少或避免記憶體調整。<br />// 4. fMinRadius: 最小半徑,當輪廓的等效半徑小於fMinRadius時,忽略該輪廓。<br />// 5. fParam: 粘連繫數,當兩個局部最大值點間的距離小於較大的局部最大值點乘上fParam時,去除較小的局部最大值點。<br />void ObjectCenter(IplImage *pBinary, IplImage *pDistance, VCenter &vecCenter, float fMinRadius, float fParam)<br />{<br />int x, y, i, j, nSize;<br />float dx, dy;<br />float fDistance, fThreshold;<br />float *pLine[3];<br />CenterIter cIter;<br />PR_Center cCenter;<br />CvSeq *pContour = NULL;<br />CvMemStorage *pStorage = NULL;<br />// 清Null 物件中心點<br />vecCenter.clear();<br />// 執行條件<br />if (pBinary && pDistance)<br />{<br />// 距離變換<br />cvDistTransform(pBinary, pDistance, CV_DIST_L2);<br />// 局部最大值點<br />for (y = 1; y < pDistance->height - 1; y++)<br />{<br />pLine[0] = (float*) (pDistance->imageData + pDistance->widthStep * (y - 1));<br />pLine[1] = (float*) (pDistance->imageData + pDistance->widthStep * y);<br />pLine[2] = (float*) (pDistance->imageData + pDistance->widthStep * (y + 1));<br />for (x = 1; x < pDistance->width - 1; x++)<br />{<br />if (pLine[1][x] >= fMinRadius)<br />{<br />if ((pLine[1][x] >= pLine[0][x - 1]) &&<br />(pLine[1][x] >= pLine[0][x]) &&<br />(pLine[1][x] >= pLine[0][x + 1]) &&<br />(pLine[1][x] >= pLine[1][x - 1]) &&<br />(pLine[1][x] >= pLine[1][x + 1]) &&<br />(pLine[1][x] >= pLine[2][x - 1]) &&<br />(pLine[1][x] >= pLine[2][x]) &&<br />(pLine[1][x] >= pLine[2][x + 1]))<br />{<br />cCenter.nObject = 0;<br />cCenter.ptCenter.x = (float) x;<br />cCenter.ptCenter.y = (float) y;<br />cCenter.fDistance = pLine[1][x];<br />vecCenter.push_back(cCenter);<br />}<br />}<br />}<br />}<br />// 尋找所有輪廓<br />pStorage = cvCreateMemStorage(0);<br />cvFindContours(pBinary, pStorage, &pContour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);<br />// 填充所有輪廓<br />cvDrawContours(pBinary, pContour, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), 2, CV_FILLED, 8, cvPoint(0, 0));<br />// 外輪廓迴圈<br />for (i = 1; pContour != NULL; pContour = pContour->h_next, i++)<br />{<br />for (cIter = vecCenter.begin(); cIter != vecCenter.end(); cIter++)<br />{<br />// 計算局部最大值點所在連通地區的編號<br />if (cIter->nObject == 0)<br />{<br />if (cvPointPolygonTest(pContour, cIter->ptCenter, 0) >= 0)<br />{<br />cIter->nObject = i;<br />}<br />}<br />}<br />}<br />cvReleaseMemStorage(&pStorage);<br />pStorage = NULL;<br />// 按編號進行排序<br />sort(vecCenter.begin(), vecCenter.end());<br />// 連通地區迴圈<br />nSize = (int) vecCenter.size();<br />for (x = 0; x < nSize;)<br />{<br />for (y = x + 1; y < nSize && vecCenter[y].nObject == vecCenter[x].nObject; y++);<br />// 處理單個連通地區<br />for (i = x; i < y - 1; i++)<br />{<br />for (j = i + 1; j < y; j++)<br />{<br />if ((vecCenter[i].fDistance >= fMinRadius) && (vecCenter[j].fDistance >= fMinRadius))<br />{<br />// 兩個局部最大值點之間的距離<br />dx = vecCenter[i].ptCenter.x - vecCenter[j].ptCenter.x;<br />dy = vecCenter[i].ptCenter.y - vecCenter[j].ptCenter.y;<br />fDistance = dx * dx + dy * dy;<br />// 距離閾值<br />fThreshold = (vecCenter[i].fDistance > vecCenter[j].fDistance) ? vecCenter[i].fDistance * fParam : vecCenter[j].fDistance * fParam;<br />fThreshold *= fThreshold;<br />// 去除非中心點<br />if (fDistance < fThreshold)<br />{<br />if (vecCenter[i].fDistance < vecCenter[j].fDistance)<br />{<br />vecCenter[i].fDistance = 0;<br />}<br />else<br />{<br />vecCenter[j].fDistance = 0;<br />}<br />}<br />}<br />}<br />}<br />x = y;<br />}<br />}<br />}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.