⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blobdetection_cc.c

📁 for the TI dm6446 platformBackground subtraction moduleMaintain a background model, which can distin
💻 C
📖 第 1 页 / 共 2 页
字号:
/**
@file   blobDetection_CC.c
@brief  implementation of blob detection algorithm for background subtraction (called by abs.c)
@author Magengyu
*/

#include "blobDetection_CC.h"
#include "backgroundSubtraction.h"
#include "../include/ema.h"

#include <stdlib.h>	// for malloc, free

extern USHORT g_iImageWidth, g_iImageHeight, g_iImageWStep;
extern BYTE g_ABSSceneType;
extern USHORT MIN_BLOB_SIZE, MAX_NOISE_SIZE;

/** the number of foreground pixels at each vertical line */
LONG* g_iaBlobPixCountH=NULL;
LONG* g_iaBlobPixCountV=NULL;
SHORT *stack_x=NULL, *stack_y=NULL;
#define BLOB_SATCK_SIZE 512

#ifdef    __cplusplus
extern "C" {
#endif

/** Allocate memory for Blob detection
* @param w,h the dimension of video to be processed
* @return void
* @author Gengyu Ma
*/
void Blob_Create(USHORT w, USHORT h)
{
	Blob_Release();

	g_iaBlobPixCountH = (LONG*)malloc(w*sizeof(LONG));
	g_iaBlobPixCountV = (LONG*)malloc(h*sizeof(LONG));
	stack_x = (SHORT*)malloc(BLOB_SATCK_SIZE*sizeof(SHORT));
	stack_y = (SHORT*)malloc(BLOB_SATCK_SIZE*sizeof(SHORT));
}

/** release memory for Blob detection
* @return void
* @author Gengyu Ma
*/
void Blob_Release()
{
	if (g_iaBlobPixCountH) free(g_iaBlobPixCountH);
	g_iaBlobPixCountH = NULL;
	if (g_iaBlobPixCountV) free(g_iaBlobPixCountV);
	g_iaBlobPixCountV = NULL;
	if (stack_x) free(stack_x);
	stack_x = NULL;
	if (stack_y) free(stack_y);
	stack_y = NULL;
}

/** Scan line filling method
* @param labelimg the label image to be filled
* @param seedx, seedy the coordinate of seed, from where filling starts
* @param box the size and position of this region
* @return number of pixels in this blob
* @author Gengyu Ma
*/
LONG Blob_ScanLineFill(BYTE* labelimg, USHORT seedx, USHORT seedy, EmaRect* box)
{
	// count how much foreground and theft pixel in this connecting regions
	// forepixnum + theftpixnum = pnum
	LONG fore_num, theft_num;
	LONG pixnum;

	INT stack_ptr = 0;
		
	BYTE *cursrc;
	
	INT displace;

	float theft_thresh;
	LONG maxheight = 0;
	SHORT x,y, xl, xr, ya;

	USHORT boxsize;

	fore_num = theft_num = 0;
	box->left = g_iImageWidth; box->right = 0;
	box->top = g_iImageHeight; box->bottom = 0;
	memset(g_iaBlobPixCountH, 0, sizeof(LONG)*g_iImageWidth);

	stack_x[0] = seedx; stack_y[0] = seedy;
	while (stack_ptr>=0)
	{
		y = stack_y[stack_ptr]; x = stack_x[stack_ptr];
		-- stack_ptr;

		// find left and right
		displace = g_iImageWStep*y + x;
		cursrc = labelimg + displace + 1;
		xl = x+1;
		while (xl>0 && *(cursrc-1)>=GAPFORE)
		{
			--xl; --cursrc; 
			*cursrc -= 100;
			if ((*cursrc)==FOREGROUND)
			{
				++ fore_num;
				++ g_iaBlobPixCountH[xl];
			}
			else if ((*cursrc)==THEFT)
			{
				++ theft_num;
				++ g_iaBlobPixCountH[xl];
			}
		}
		xr = x;
		cursrc = labelimg + displace;
		while (xr<g_iImageWidth-1 && *(cursrc+1)>=GAPFORE) 
		{
			++xr; ++cursrc;
			*cursrc -= 100; 
			if ((*cursrc)==FOREGROUND)
			{
				++ fore_num;
				++ g_iaBlobPixCountH[xr];
			}
			else if ((*cursrc)==THEFT)
			{
				++ theft_num;
				++ g_iaBlobPixCountH[xr];
			}
		}
		// update box position
		box->left = EMA_MIN(box->left, xl);
		box->right = EMA_MAX(box->right, xr);
		box->top = EMA_MIN(box->top, y);
		box->bottom = EMA_MAX(box->bottom, y);

		// find above
		ya = y-1;
		if (ya>=0)
		{
			displace = g_iImageWStep*ya + xl;
			cursrc = labelimg + displace;
			for (x=xl; x<=xr; x++)
			{
				if (*(cursrc)>=GAPFORE && (x==xl || *(cursrc-1)<GAPFORE))
				{
					++ stack_ptr;
					stack_x[stack_ptr] = x;
					stack_y[stack_ptr] = ya;
				}
				++ cursrc;
			}
		}

		// find bellow
		ya = y+1;
		if (ya<g_iImageHeight)
		{
			displace = g_iImageWStep*ya + xl;
			cursrc = labelimg + displace;
			for (x=xl; x<=xr; x++)
			{
				if (*(cursrc)>=GAPFORE && (x==xl || *(cursrc-1)<GAPFORE))
				{
					++ stack_ptr;
					stack_x[stack_ptr] = x;
					stack_y[stack_ptr] = ya;
				}
				++ cursrc;
			}
		}

		if (stack_ptr>=BLOB_SATCK_SIZE-1) break;
	}
	
	box->top += 3; box->bottom -= 3;
	++ box->left; -- box->right;

	// analyze box
	pixnum = fore_num + theft_num;
	if (pixnum<MIN_BLOB_SIZE) return pixnum;
	maxheight = 0;
	for (x=box->left; x<box->right; x++)
		maxheight = EMA_MAX(maxheight, g_iaBlobPixCountH[x]);

	// determine blob type
	if (pixnum<1000) theft_thresh = 1.0f;
	else if (pixnum<10000) theft_thresh = 1.7f;
	else theft_thresh = 2.5f;
	if (theft_num>fore_num*theft_thresh) box->evt = EMA_THEFT;
	else box->evt = EMA_NOEVENT;

	// shadow removal by shape
	if (pixnum>200)
	{
		xl = box->left;
		while (g_iaBlobPixCountH[xl]*3<maxheight*2)	xl++;
		while (box->left<=xl-maxheight/4
			&& g_iaBlobPixCountH[box->left]*2<maxheight)
				box->left++;
		xr = box->right;
		while (g_iaBlobPixCountH[xr]*3<maxheight*2) xr--;
		while (box->right>=xr+maxheight/4
			&& g_iaBlobPixCountH[box->right]*2<maxheight)
				box->right--;
	}

	// remove blobs with very few foreground pixels in them
	boxsize = (box->right-box->left)*(box->bottom-box->top);
	if (pixnum>10 && (pixnum+4)<boxsize/5) return -1;
	if (pixnum<(box->bottom-box->top)*3) return -1;
	if (pixnum<(box->right-box->left)*3) return -1;

	return pixnum;
}

/** Scan line filling method
* @param img the label image to be filled
* @param seedx, seedy the coordinate of seed, from where filling starts
* @param box the size and position of this region
* @return number of pixels in this blob
* @author Gengyu Ma
*/
INT Blob_ScanLineFill_Shadow(BYTE* img, USHORT seedx, USHORT seedy, EmaRect* box)
{
	typedef struct tag_seed
	{
		USHORT x;
		USHORT y;
		USHORT rightlen;
		struct tag_seed *next;
	}seed;

	INT pnum = 0;
	// count how much foreground and theft pixel in this connecting regions
	// forepixnum + theftpixnum = pnum
	UINT forepixnum = 0, theftpixnum = 0;

	// calculate how many adjacent pixels are shadow pixels
	USHORT shadowborder = 0, totalborder = 0;

	seed *head, *p1;

	SHORT notshadowpos;
	
	BYTE *cursrc;
	
	INT displace;

	float theft_thresh;
	LONG maxheight = 0;
	USHORT x, nl, nr;

	LONG boxsize;
	LONG pixnum;

	// vertical projection map for strong shadow removal
	memset(g_iaBlobPixCountH, 0, g_iImageWidth*sizeof(LONG));

	box->left = box->right = seedx;
	box->top = box->bottom = seedy;

	//init head node
	p1 = (seed*) malloc(sizeof(seed));
	p1 ->x = seedx;
	p1 ->y = seedy;
	p1 ->rightlen = 1;
	head = p1;
	head ->next = NULL;
	g_iaBlobPixCountH[p1->x]++;

	displace = seedy*g_iImageWidth + seedx;
	img[displace]--;
	pnum = 1;
	if (img[displace]==THEFT) theftpixnum++;
	else forepixnum++;
	

	// main loop
	while(head!=NULL)
	{
		SHORT xleft = head->x - 1;
		SHORT xright = head->x + head->rightlen;
		SHORT xup = xleft;
		SHORT yup = head->y - 1;
		SHORT xdown = xleft;
		SHORT ydown = head->y + 1;
		SHORT	startx = -1;
		SHORT endx = -1;

		displace = head->y*g_iImageWidth;

		// remove current head
		p1 = head;
		head = p1->next;
		free(p1);

		// left pixels
		notshadowpos = xleft+1;
		cursrc = img + displace + xleft;
		while (xleft>=0)
		{
			if ( *(cursrc)==THEFTPIXEL || *(cursrc)==FOREPIXEL)
			{
				(*cursrc) --;
				g_iaBlobPixCountH[xleft]++;
				xleft--;
				notshadowpos--;
				cursrc--;
				pnum++;
				if (*cursrc==THEFT) theftpixnum++;
				else forepixnum++;
			}
			else if (*cursrc==GAPFORE)
			{
				(*cursrc) --;
				xleft--;
				cursrc--;
			}
			else 
			{
				totalborder ++;
				if (*cursrc==GAPFORE) shadowborder ++;
				break;
			}
		}
		xleft ++;
		if (box->left>notshadowpos) box->left = notshadowpos;

		// right pixels
		cursrc = img + displace + xright;
		notshadowpos = xright-1;
		while (xright<g_iImageWidth)
		{
			if ( *(cursrc)==THEFTPIXEL || *(cursrc)==FOREPIXEL)
			{
				(*cursrc) --;
				g_iaBlobPixCountH[xright]++;
				notshadowpos++;
				xright++;
				cursrc++;
				pnum++;
				if (*cursrc==THEFT) theftpixnum++;
				else forepixnum++;
			}
			else if (*cursrc==GAPFORE)
			{
				(*cursrc) --;
				xright++;
				cursrc++;
			}
			else
			{
				totalborder ++;
				if (*cursrc==GAPFORE) shadowborder ++;
				break;
			}
		}
		xright --;
		if (box->right<notshadowpos) box->right = notshadowpos;

		// top line
		startx = -1;
		endx = -1;
		notshadowpos = yup+1;
		if (yup>=0)
		{
			displace = yup*g_iImageWidth + xleft;
			cursrc = img + displace;
			for (xup=xleft; xup<=xright; xup++)
			{
				if (*cursrc==BACKGROUND || *cursrc==GAPFORE) totalborder ++;
				if (*cursrc==GAPFORE) shadowborder ++;
				if (*cursrc==THEFTPIXEL || *cursrc==FOREPIXEL)
				{
					if (startx<0) startx = xup;
					(*cursrc) --;
					g_iaBlobPixCountH[xup]++;
					pnum++;
					if (*cursrc==THEFT) theftpixnum++;
					else forepixnum++;
				}
				else if (*cursrc==GAPFORE)
				{
					if (startx<0) startx = xup;
					(*cursrc) --;
				}
				else
				{
					if (startx>=0)
					{
						endx = xup-1;
						p1 = (seed*) malloc(sizeof(seed));
						p1 ->x = startx;
						p1 ->y = yup;
						p1->rightlen = endx-startx+1;
						p1 ->next = head;
						head = p1;

						notshadowpos = yup;
						startx = -1;
					}
				}
				cursrc++;
			}
		}
		if (startx>=0)
		{
			endx = xright;
			p1 = (seed*) malloc(sizeof(seed));
			p1 ->x = startx;
			p1 ->y = yup;
			p1->rightlen = endx-startx+1;
			p1 ->next = head;
			head = p1;

			notshadowpos = yup;
			startx = -1;
		}
		if (box->top>yup) box->top = yup;

		// bottom line
		startx = -1;
		endx = -1;
		notshadowpos = ydown-1;
		if (ydown<g_iImageHeight)
		{
			displace = ydown*g_iImageWidth + xleft;
			cursrc = img + displace;
			for (xdown=xleft; xdown<=xright; xdown++)
			{
				if (*cursrc==BACKGROUND || *cursrc==GAPFORE) totalborder ++;
				if (*cursrc==GAPFORE) shadowborder ++;
				if (*cursrc==THEFTPIXEL || *cursrc==FOREPIXEL)
				{
					if (startx<0) startx = xdown;
					(*cursrc) --;
					g_iaBlobPixCountH[xdown]++;
					pnum++;
					if (*cursrc==THEFT) theftpixnum++;
					else forepixnum++;
				}
				else if (*cursrc==GAPFORE)
				{
					if (startx<0) startx = xdown;
					(*cursrc) --;
				}				
				else
				{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -