📄 enteringblobdetection.cpp
字号:
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
/*
This file contain implementation of virtual interface of CvBlobDetector
this implementation based on simple algorithm
new blob is detected when several successive frames contains connected componets
which have uniform motion with not high speed.
Also separation from border and already tracked blobs are considered.
*/
//#define USE_OBJECT_DETECTOR
#include "_cvaux.h"
static int CompareContour(const void* a, const void* b, void* )
{
float dx,dy;
float h,w,ht,wt;
CvPoint2D32f pa,pb;
CvRect ra,rb;
CvSeq* pCA = *(CvSeq**)a;
CvSeq* pCB = *(CvSeq**)b;
ra = ((CvContour*)pCA)->rect;
rb = ((CvContour*)pCB)->rect;
pa.x = ra.x + ra.width*0.5f;
pa.y = ra.y + ra.height*0.5f;
pb.x = rb.x + rb.width*0.5f;
pb.y = rb.y + rb.height*0.5f;
w = (ra.width+rb.width)*0.5f;
h = (ra.height+rb.height)*0.5f;
dx = (float)(fabs(pa.x - pb.x)-w);
dy = (float)(fabs(pa.y - pb.y)-h);
//wt = MAX(ra.width,rb.width)*0.1f;
wt = 0;
ht = MAX(ra.height,rb.height)*0.3f;
if(dx < wt && dy < ht) return 1;
return 0;
}
void cvFindBlobsByCCClasters(IplImage* pFG, CvBlobSeq* pBlobs, CvMemStorage* storage)
{/* create contours */
IplImage* pIB = NULL;
CvSeq* cnt = NULL;
CvSeq* cnt_list = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvSeq*), storage );
CvSeq* clasters = NULL;
int claster_cur, claster_num;
pIB = cvCloneImage(pFG);
cvThreshold(pIB,pIB,128,255,CV_THRESH_BINARY);
cvFindContours(pIB,storage, &cnt, sizeof(CvContour), CV_RETR_EXTERNAL);
cvReleaseImage(&pIB);
/* create cnt_list*/
/* process each contours*/
for(;cnt;cnt=cnt->h_next)
{
cvSeqPush( cnt_list, &cnt);
}
claster_num = cvSeqPartition( cnt_list, storage, &clasters, CompareContour, NULL );
for(claster_cur=0;claster_cur<claster_num;++claster_cur)
{
int cnt_cur;
CvBlob NewBlob;
double M00,X,Y,XX,YY; /* image moments */
CvMoments m;
CvRect rect_res = cvRect(-1,-1,-1,-1);
CvMat mat;
for(cnt_cur=0;cnt_cur<clasters->total;++cnt_cur)
{
CvRect rect;
CvSeq* cnt;
int k = *(int*)cvGetSeqElem( clasters, cnt_cur );
if(k!=claster_cur) continue;
cnt = *(CvSeq**)cvGetSeqElem( cnt_list, cnt_cur );
rect = ((CvContour*)cnt)->rect;
if(rect_res.height<0)
{
rect_res = rect;
}
else
{/* unite rects */
int x0,x1,y0,y1;
x0 = MIN(rect_res.x,rect.x);
y0 = MIN(rect_res.y,rect.y);
x1 = MAX(rect_res.x+rect_res.width,rect.x+rect.width);
y1 = MAX(rect_res.y+rect_res.height,rect.y+rect.height);
rect_res.x = x0;
rect_res.y = y0;
rect_res.width = x1-x0;
rect_res.height = y1-y0;
}
}
if(rect_res.height < 1 || rect_res.width < 1)
{
X = 0;
Y = 0;
XX = 0;
YY = 0;
}
else
{
cvMoments( cvGetSubRect(pFG,&mat,rect_res), &m, 0 );
M00 = cvGetSpatialMoment( &m, 0, 0 );
if(M00 <= 0 ) continue;
X = cvGetSpatialMoment( &m, 1, 0 )/M00;
Y = cvGetSpatialMoment( &m, 0, 1 )/M00;
XX = (cvGetSpatialMoment( &m, 2, 0 )/M00) - X*X;
YY = (cvGetSpatialMoment( &m, 0, 2 )/M00) - Y*Y;
}
NewBlob = cvBlob(rect_res.x+(float)X,rect_res.y+(float)Y,(float)(4*sqrt(XX)),(float)(4*sqrt(YY)));
pBlobs->AddBlob(&NewBlob);
}/* next cluster */
#if 0
{// debug info
IplImage* pI = cvCreateImage(cvSize(pFG->width,pFG->height),IPL_DEPTH_8U,3);
cvZero(pI);
for(claster_cur=0;claster_cur<claster_num;++claster_cur)
{
int cnt_cur;
CvScalar color = CV_RGB(rand()%256,rand()%256,rand()%256);
for(cnt_cur=0;cnt_cur<clasters->total;++cnt_cur)
{
CvSeq* cnt;
int k = *(int*)cvGetSeqElem( clasters, cnt_cur );
if(k!=claster_cur) continue;
cnt = *(CvSeq**)cvGetSeqElem( cnt_list, cnt_cur );
cvDrawContours( pI, cnt, color, color, 0, 1, 8);
}
CvBlob* pB = pBlobs->GetBlob(claster_cur);
int x = cvRound(CV_BLOB_RX(pB)), y = cvRound(CV_BLOB_RY(pB));
cvEllipse( pI,
cvPointFrom32f(CV_BLOB_CENTER(pB)),
cvSize(MAX(1,x), MAX(1,y)),
0, 0, 360,
color, 1 );
}
cvNamedWindow( "Clusters", 0);
cvShowImage( "Clusters",pI );
cvReleaseImage(&pI);
}/* debug info */
#endif
}/* cvFindBlobsByCCClasters */
/* simple blob detector */
/* numer of successive frame to analyse */
#define EBD_FRAME_NUM 5
class CvBlobDetectorSimple:public CvBlobDetector
{
public:
CvBlobDetectorSimple();
~CvBlobDetectorSimple();
int DetectNewBlob(IplImage* pImg, IplImage* pFGMask, CvBlobSeq* pNewBlobList, CvBlobSeq* pOldBlobList);
void Release(){delete this;};
protected:
IplImage* m_pMaskBlobNew;
IplImage* m_pMaskBlobExist;
/* lists of connected components detected on previouse frames */
CvBlobSeq* m_pBlobLists[EBD_FRAME_NUM];
};
/* Blob detector creator (sole interface function for this file) */
CvBlobDetector* cvCreateBlobDetectorSimple(){return new CvBlobDetectorSimple;};
/* Constructor of BlobDetector */
CvBlobDetectorSimple::CvBlobDetectorSimple()
{
int i = 0;
m_pMaskBlobNew = NULL;
m_pMaskBlobExist = NULL;
for(i=0;i<EBD_FRAME_NUM;++i)m_pBlobLists[i] = NULL;
}
/* destructor of BlobDetector*/
CvBlobDetectorSimple::~CvBlobDetectorSimple()
{
int i;
if(m_pMaskBlobExist) cvReleaseImage(&m_pMaskBlobExist);
if(m_pMaskBlobNew) cvReleaseImage(&m_pMaskBlobNew);
for(i=0;i<EBD_FRAME_NUM;++i)delete m_pBlobLists[i];
}/* cvReleaseBlobDetector */
/* cvDetectNewBlobs return 1 and fill blob pNewBlob by blob parameters if new blob is detected */
int CvBlobDetectorSimple::DetectNewBlob(IplImage* /*pImg*/, IplImage* pFGMask, CvBlobSeq* pNewBlobList, CvBlobSeq* pOldBlobList)
{
int res = 0;
CvSize S = cvSize(pFGMask->width,pFGMask->height);
if(m_pMaskBlobNew == NULL ) m_pMaskBlobNew = cvCreateImage(S,IPL_DEPTH_8U,1);
if(m_pMaskBlobExist == NULL ) m_pMaskBlobExist = cvCreateImage(S,IPL_DEPTH_8U,1);
/* shift blob list */
{
int i;
if(m_pBlobLists[0]) delete m_pBlobLists[0];
for(i=1;i<EBD_FRAME_NUM;++i)m_pBlobLists[i-1]=m_pBlobLists[i];
m_pBlobLists[EBD_FRAME_NUM-1] = new CvBlobSeq;
}/* shift blob list */
/* create exist blob mask */
cvCopy(pFGMask, m_pMaskBlobNew);
/* create contours and add new blobs to blob list */
{/* create blobs */
CvBlobSeq Blobs;
CvMemStorage* storage = cvCreateMemStorage();
#if 1
{/* glue contours */
cvFindBlobsByCCClasters(m_pMaskBlobNew, &Blobs, storage );
}/* glue contours */
#else
{ /**/
IplImage* pIB = cvCloneImage(m_pMaskBlobNew);
CvSeq* cnts = NULL;
CvSeq* cnt = NULL;
cvThreshold(pIB,pIB,128,255,CV_THRESH_BINARY);
cvFindContours(pIB,storage, &cnts, sizeof(CvContour), CV_RETR_EXTERNAL);
/* process each contours*/
for(cnt = cnts;cnt;cnt=cnt->h_next)
{
CvBlob NewBlob;
/* image moments */
double M00,X,Y,XX,YY;
CvMoments m;
CvRect r = ((CvContour*)cnt)->rect;
CvMat mat;
if(r.height < S.height*0.02 || r.width < S.width*0.02) continue;
cvMoments( cvGetSubRect(m_pMaskBlobNew,&mat,r), &m, 0 );
M00 = cvGetSpatialMoment( &m, 0, 0 );
if(M00 <= 0 ) continue;
X = cvGetSpatialMoment( &m, 1, 0 )/M00;
Y = cvGetSpatialMoment( &m, 0, 1 )/M00;
XX = (cvGetSpatialMoment( &m, 2, 0 )/M00) - X*X;
YY = (cvGetSpatialMoment( &m, 0, 2 )/M00) - Y*Y;
NewBlob = cvBlob(r.x+(float)X,r.y+(float)Y,(float)(4*sqrt(XX)),(float)(4*sqrt(YY)));
Blobs.AddBlob(&NewBlob);
}/* next contour */
cvReleaseImage(&pIB);
}/* one contour - one blob */
#endif
{/* Delete small and intersected blobs */
int i;
for(i=Blobs.GetBlobNum();i>0;i--)
{
CvBlob* pB = Blobs.GetBlob(i-1);
if(pB->h < S.height*0.02 || pB->w < S.width*0.02)
{
Blobs.DelBlob(i-1);
continue;
}
if(pOldBlobList)
{
int j;
for(j=pOldBlobList->GetBlobNum();j>0;j--)
{
CvBlob* pBOld = pOldBlobList->GetBlob(j-1);
if((fabs(pBOld->x-pB->x) < (CV_BLOB_RX(pBOld)+CV_BLOB_RX(pB))) &&
(fabs(pBOld->y-pB->y) < (CV_BLOB_RY(pBOld)+CV_BLOB_RY(pB))))
{/* intersection is present, delete blob from list*/
Blobs.DelBlob(i-1);
break;
}
}/* checl next old blob */
}/*if pOldBlobList */
}/* check next blob */
}/* Delete small and intersected blobs */
{/* bubble sort blobs by size */
int N = Blobs.GetBlobNum();
int i,j;
for(i=1;i<N;++i)
{
for(j=i;j>0;--j)
{
CvBlob temp;
float AreaP, AreaN;
CvBlob* pP = Blobs.GetBlob(j-1);
CvBlob* pN = Blobs.GetBlob(j);
AreaP = CV_BLOB_WX(pP)*CV_BLOB_WY(pP);
AreaN = CV_BLOB_WX(pN)*CV_BLOB_WY(pN);
if(AreaN < AreaP)break;
temp = pN[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -