连通域相关

19 篇文章 0 订阅
10 篇文章 0 订阅

OpenCV统计米粒数目-计算联通区域的个数及联通区域内像素的个数

二值图像统计连通区域C语言版

二值图像连通域标记算法与代码

二值图像连通域标记

二值图像连通区域标记(OpenCV版)

数字图像处理-编程实现染色体计数 C语言实现

C语言(高速算法)去除二值图中的小面积连通区域

#include <stdio.h>
#include <math.h>

#include <time.h>
#include <c6x.h>
#include <stdlib.h>
#include <string.h>

#include "reader.h"
#include "grey2color.h"
#include "rgb2yuv.h"

/*
 * 仅限使用24位bmp格式图片
 *	656--512
 * */
/*******************************************************algrithem***********************************************************/

void IMG_thr_8_cn
(
    const unsigned char *grey,
    const unsigned char *BackGround,
    unsigned char       *restrict thresholdArray,
    short cols,
    short rows,
    unsigned char       threshold
)
{
    int i;
    int pixels = rows * cols;

#ifndef NOASSUME
    _nassert((int)grey   % 8  == 0);
    _nassert((int)grey  % 8  == 0);
    _nassert((int)thresholdArray  % 8  == 0);
    _nassert(pixels         % 16 == 0);
    _nassert(pixels              >= 16);
#endif
	int temp = 0;

	for(i=0;i < pixels;i++)
	{
		temp = abs(grey[i] - BackGround[i]);
		thresholdArray[i] = temp > threshold ? 255 : 0;
	}

}

/****
 * 图像缩放
 * (宽高只支持4的倍数)
 * *****/
void imageSmall(unsigned char *restrict inputImage,
		unsigned char * outputImage,
		const int width,
		const int height)
{
    _nassert(width > 0);
    _nassert(height > 0);
    _nassert((int)width % 4 == 0);
    _nassert((int)height % 4 == 0);

	int i,j;

	int temp = 0;
	int i_out = 0;
	int j_out = 0;
//	int h_index = height >> 2;
	int w_index = width >> 2;

	for (j = 0; j < height; j+=4)
	{
		for (i = 0; i < width; i+=4)
		{
			temp = *(inputImage + width*j + i);
			i_out = i >> 2;
			j_out = j >> 2;
			*(outputImage + w_index*j_out + i_out) = temp;
		}
	}
}

void imageBig(unsigned char *restrict inputImage,
		unsigned char * outputImage,
		const int width,
		const int height)
{
    _nassert(width > 0);
    _nassert(height > 0);
    _nassert((int)width % 4 == 0);
    _nassert((int)height % 4 == 0);

	int i,j;

	int temp = 0;
	int i_out = 0;
	int j_out = 0;
	int w_index = width >> 2;

	for (j = 0; j < height; j++)
	{
		for (i = 0; i < width; i++)
		{
			i_out = i >> 2;
			j_out = j >> 2;
			temp = *(inputImage + w_index*j_out + i_out);
			*(outputImage + width*j + i) = temp;
		}
	}
}



void areaCount(int *restrict labelmap, int *restrict area, const int width, const int height, const int labelIndex)
{
    _nassert(width > 0);
    _nassert(height > 0);
    _nassert((int)width % 4 == 0);
    _nassert((int)height % 4 == 0);

    int i,cx,cy,index = 0;
    int realWidth = width - 1;
    int realHeight = height - 1;

	#pragma MUST_ITERATE(120,,) //C函数循环优化
    for(cy = 1; cy < realHeight; cy++)					//统计各个连通域的面积
    {
	#pragma MUST_ITERATE(160,,) //C函数循环优化
        for(cx = 1; cx < realWidth; cx++)
        {
             index = cy * width + cx;
             for(i = 1; i < labelIndex + 1; i++)
             {
            	 area[i] = labelmap[index] == i ? area[i] + 1 : area[i];
             }
         }
    }
}

typedef struct QNode{
    int data;
    struct QNode *next;
}QNode;

typedef struct Queue{
    struct QNode* first;
    struct QNode* last;
}Queue;

void PushQueue(Queue *queue, int data){
    QNode *p = NULL;
    p = (QNode*)malloc(sizeof(QNode));
    p->data = data;
    if(queue->first == NULL){
        queue->first = p;
        queue->last = p;
        p->next = NULL;
    }
    else{
        p->next = NULL;
        queue->last->next = p;
        queue->last = p;
    }
}

int PopQueue(Queue *queue){
    QNode *p = NULL;
    int data;
    if(queue->first == NULL){
        return -1;
    }
    p = queue->first;
    data = p->data;
    if(queue->first->next == NULL){
        queue->first = NULL;
        queue->last = NULL;
    }
    else{
        queue->first = p->next;
    }
    free(p);
    return data;
}

static int NeighborDirection[8][2] = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};

void SearchNeighbor(unsigned char *bitmap, int width, int height, int *labelmap,
                    int labelIndex, int pixelIndex, Queue *queue){
    int searchIndex, i, length;
    labelmap[pixelIndex] = labelIndex;
    length = width * height;
    for(i = 0;i < 8;i++)
    {
        searchIndex = pixelIndex + NeighborDirection[i][0] * width + NeighborDirection[i][1];
        if(searchIndex > 0 && searchIndex < length &&
            bitmap[searchIndex] == 255 && labelmap[searchIndex] == 0)
        {
            labelmap[searchIndex] = labelIndex;
            PushQueue(queue, searchIndex);
        }
    }
}

int ConnectedComponentLabeling(unsigned char *bitmap, unsigned char *out, int width, int height, int *ConnectedComponentArea, int *labelmap)
{
	int i;
    int cx, cy, index, popIndex, labelIndex = 0;
    Queue *queue = NULL;
    queue = (Queue*)malloc(sizeof(Queue));
    queue->first = NULL;
        queue->last = NULL;
    memset(labelmap, 0, width * height);
    for(cy = 1; cy < height - 1; cy++){
        for(cx = 1; cx < width - 1; cx++){
            index = cy * width + cx;
            if(bitmap[index] == 255 && labelmap[index] == 0){
                labelIndex++;
                SearchNeighbor(bitmap, width, height, labelmap, labelIndex, index, queue);

                popIndex = PopQueue(queue);
                while(popIndex > -1){
                SearchNeighbor(bitmap, width, height, labelmap, labelIndex, popIndex, queue);
                    popIndex = PopQueue(queue);
                }
            }
        }
    }
    free(queue);					//5 221 565	【0303	1 012 986】

    /******************************************/
    int area[400];									//定义连通域面积,最多允许400个连通域
    for(i = 0; i < 400 ; i++)area[i] = 0;
/*
    int realWidth = width - 1;
    int realHeight = height - 1;
    int temp;
        for(cy = 1; cy < realHeight; cy++)				//统计各个连通域的面积
        {
            for(cx = 1; cx < realWidth; cx++)
            {
                index = cy * width + cx;
                for(i = 1; i < labelIndex + 1; i+=2)
                {
                   if(labelmap[index] == i)				//1 042 908
                   {
                       area[i]++;
                   }
                }
//                for(i = 1; i < labelIndex + 1; i+=2)		//978 528
//                {
//                	if(labelmap[index] == i)
//                	{
//                		area[i]++;
//                	}
//                	if(labelmap[index] == i + 1)
//                	{
//                		area[i + 1]++;
//                	}
//                }
            }
        }
*/
        areaCount(labelmap, area, width, height, labelIndex);		//【0303	687 390】

        int label[10] = {0};										//允许存留连通域个数,最多9个,label[0]不用
        int piclabel = 1;									//标签个数
        for(i = 1; i < labelIndex + 1; i++)
        {
        	printf("area[%d] = %d \n", i, area[i]);
        	if(area[i] < 2500 && area[i] > 80)
        	{
        		label[piclabel] = i;								//只保存面积符合要求的连通区域的标签
        		printf("gas label[%d] = %d \n", piclabel, label[piclabel]);
        		piclabel++;
        	}
        }
        printf("main piclabel num = %d \n", piclabel - 1);


        int num = 0;
        for(cy = 1; cy < height - 1; cy++)
        {
            for(cx = 1; cx < width - 1; cx++)
            {
                index = cy * width + cx;
                for(i=1; i < piclabel ; i++)
                {
                	if(labelmap[index] == label[i])
                	{
                		out[index] = 255;
                		num++;
                	}
                }
            }
        }

        *ConnectedComponentArea = num;
    return labelIndex;								//52 090 225	【0303	563 112】
}




/*************************************************************************/
int main(void)
{
	int i, j;
	int width;
	int height;
	int row,col;
	unsigned char *picdata01 = (unsigned char*)0x90000000;
	unsigned char *picdata02 = (unsigned char*)0x90100000;
	unsigned short *bitwidth = (unsigned short *)(picdata01 + 0x00000012);
	unsigned short *bitheight = (unsigned short *)(picdata01 + 0x00000016);

	height = *bitheight;
	width = *bitwidth;
	row = height;
	col = width;

	unsigned char *r1 = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *g1 = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *b1 = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *r2 = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *g2 = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *b2 = (unsigned char *)malloc(width*height*sizeof(unsigned char));

	reader(picdata01, r1, g1, b1, width, height);
	reader(picdata02, r2, g2, b2, width, height);
	/**********************获取背景帧和后续数据帧*************************/
	unsigned char *grey = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *BackGround = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char* outpic = (unsigned char*)malloc(row*col*sizeof(unsigned char));

	int temp = 0;
	for(i=0;i < row;i++)
	{
		for(j=0;j<col;j++)
		{
			temp = (b1[i*col + j] + g1[i*col + j] + r1[i*col + j])/3;
			BackGround[i*col + j] = temp;
		}
	}

	for(i=0;i < row;i++)
	{
		for(j=0;j<col;j++)
		{
			temp = (b2[i*col + j] + g2[i*col + j] + r2[i*col + j])/3;
			grey[i*col + j] = temp;
		}
	}
	/**********************获取背景帧和后续数据帧*************************/

		int threshold = 10;			//一般情况下取10
		int ConCompLabNum = 0;
		unsigned char* difference = (unsigned char*)malloc(row*col*sizeof(unsigned char));				//3 774 824
		unsigned char* thresholdArray = (unsigned char*)malloc(row*col*sizeof(unsigned char));

		unsigned char *outb = outpic;
		unsigned char *outg = outb + row*col;
		unsigned char *outr = outg + row*col;


		IMG_thr_8_cn(grey, BackGround, thresholdArray, col, row, threshold);			//671 773

		unsigned char* smallThArr = (unsigned char*)malloc(row/4*col/4*sizeof(unsigned char));
		unsigned char* smallOut = (unsigned char*)malloc(row/4*col/4*sizeof(unsigned char));
		int* labelpic = (int*)malloc(row/4*col/4*sizeof(int));

		imageSmall(thresholdArray, smallThArr, width, height);							//[0303	43 808]
		int area;
		ConCompLabNum = ConnectedComponentLabeling(smallThArr, smallOut, width/4, height/4, &area, labelpic);		//[0303	2 270 238]
		printf("ConnectedComponentLabeling = %d \n",ConCompLabNum);

		unsigned char* out = (unsigned char*)malloc(row*col*sizeof(unsigned char));
		imageBig(smallOut, out, width, height);											//[0303 	344 609]

		int* colorCoordX = (int*)malloc(area*16*sizeof(int));
		int* colorCoordY = (int*)malloc(area*16*sizeof(int));
		int index = 0;
		for(i=0;i < row;i++)															//[0303		1 869 132]
		{
			for(j=0;j<col;j++)
			{
				if(out[i*col + j] > 0)
				{
					outb[i*col + j] = ToRed(grey[i*col + j] * 5);
					outg[i*col + j] = ToGreen(grey[i*col + j] * 5);
					outr[i*col + j] = ToBlue(grey[i*col + j] * 5);

//					outb[i*col + j] = 255;
//					outg[i*col + j] = 255;
//					outr[i*col + j] = 255;

					colorCoordX[index] = j;												// 1 886 971
					colorCoordY[index] = i;
					index++;
				}
				else
				{
					outb[i*col + j] = grey[i*col + j];
					outg[i*col + j] = grey[i*col + j];
					outr[i*col + j] = grey[i*col + j];
//					outb[i*col + j] = 0;
//					outg[i*col + j] = 0;
//					outr[i*col + j] = 0;
				}
			}
		}

		unsigned char *pYUV = (unsigned char *)malloc(row*col*2*sizeof(unsigned char));
//		BGR24ToYUV420_Packed(outpic, pYUV, colorCoordX, colorCoordY, 4*area, width, height);				//5 299 962
																											//	218 470
		BGR24ToYUV422_Packed(outpic, pYUV, colorCoordX, colorCoordY, 16*area, width, height);
		free(difference);
		free(thresholdArray);
		free(labelpic);
		free(smallThArr);
		free(smallOut);

		free(out);
		free(colorCoordX);
		free(colorCoordY);
		free(pYUV);
	/***********************输出************************/

	free(b1);
	free(g1);
	free(r1);

	free(b2);
	free(g2);
	free(r2);

	free(grey);
	free(BackGround);

	free(outpic);

	return 0;
}


/*
 * main.c
 */
#include <stdio.h>
#include <math.h>

#include <time.h>
#include <c6x.h>
#include <stdlib.h>
#include <string.h>

#include "reader.h"
#include "grey2color.h"

/*
 * 仅限使用24位bmp格式图片
 *	656--512
 * */
/*******************************************************algrithem***********************************************************/
typedef struct Node_Int //链表的整型节点,其中定两个data点,是为了解决pair的特性
{
	int data1;
	int data2;
	struct Node_Int * pNext;
} NODE, *PNODE;

//整型栈
typedef struct Stack_Int {
	PNODE pTop;
	PNODE pBottom;
	int size; //栈的大小

} STACK_INT, *PSTACK;
/************初始化栈*************/
void StackInit(PSTACK pStack)
{
	pStack->pTop = (PNODE)malloc(sizeof(NODE));
	if (NULL == pStack->pTop)
	{
		printf("内存分配失败");
	}
	else
	{
		pStack->pBottom = pStack->pTop;
		pStack->pTop->pNext = NULL;
		pStack->size = 0;
	}
}

//压栈
void StackPush(PSTACK pStack, int val1, int val2)
{
	PNODE pNew = (PNODE)malloc(sizeof(NODE));//每次压栈前,先分配一个节点的内存
	pNew->data1 = val1;
	pNew->data2 = val2;
	pNew->pNext = pStack->pTop;
	pStack->pTop = pNew;
	pStack->size++;
}

//是否为空栈
int StackIsEmpty(PSTACK pS)//是否为空栈
{
	if (pS->pTop == pS->pBottom)
	{
		return 1;
	}
	else
		return 0;
}

//出栈
int StackPop(PSTACK pS, int *pVal1, int *pVal2)//把pS所指向的栈出栈一次
{
	if (StackIsEmpty(pS))
	{
		return 0;
	}
	else
	{
		PNODE r = pS->pTop;
		*pVal1 = r->data1;
		*pVal2 = r->data2;
		pS->pTop = r->pNext;
		free(r);
		r = NULL;
		pS->size--;
		return 1;
	}
}
//遍历
void StackTraverse(PSTACK pStack)//遍历栈中元素
{
	PNODE pNew = pStack->pTop;
	while (pNew != pStack->pBottom)
	{
		printf("%d,%d \n", pNew->data1, pNew->data2);
		pNew = pNew->pNext;
	}
	printf("\n");
}


//清空栈
void StackClear(PSTACK pS)//释放栈空间
{
	if (StackIsEmpty(pS))
	{
		return;
	}
	else
	{
		PNODE pT = pS->pTop;
		PNODE q = NULL;

		while (pT != pS->pBottom)
		{
			printf("stack free \n");
			q = pT->pNext;
			free(pT);
			pT = q;
		}
		pS->pTop = pS->pBottom;
		pS->size = 0;
	}
}

int GetDiffImage(unsigned char *inputImg1,			//输入:第一幅图
		unsigned char *inputImg2, 			//输入:第二幅图
		unsigned char *diffImg, 			//输出:差分图
		int width, int height)
{
	int i;

	if(inputImg1 == NULL || inputImg2 == NULL || diffImg == NULL)
	{

		printf("输入的图像数为空!!\n");
		return 0;
	}

	int temp = 0;
	for (i = 0; i < width * height; i++)
	{
		temp = abs(*(inputImg2 + i) - *(inputImg1 + i));
		*(diffImg + i) = temp;
	}
	return 1;
}
//将图像二值化
int ImageToThresholdImage(unsigned char *srcImg,	//输入:源图
			unsigned char *outImg,		//输出:输出图
			int width, int height,
			int threshold) 			//输出:域值
{
	if(srcImg == NULL || outImg == NULL)
	{
		printf("输入的图像数为空!!\n");
		return 0;
	}
	int i, j;

	for (j = 0; j < height; j++)
	{
		for (i = 0; i < width; i++)
		{
			if (*(srcImg + width*j + i) > threshold)
			{
				*(outImg + width*j + i) = 1;
//				printf("outImg[%d] = %d \n",width*j + i, outImg[width*j + i]);
			}
			else
			{
				*(outImg + width*j + i) = 0;
			}
		}
	}
	return 1;
}

//数组的存储顺序为maxX,maxY,minX,minY
void stackToArray(STACK_INT inputPoints, int * outputPoints)
{
	int i;
	//确保空间足够
	if (inputPoints.size>2000)
	{
		printf("输出数组空间不够!\n");
		return;
	}

	int count = 2 * inputPoints.size;
	//translate
	int stackPopVal1, stackPopVal2;
	for (i = 0; i < count; i+=2)
	{
		StackPop(&inputPoints, &stackPopVal1, &stackPopVal2);
		*(outputPoints + i) = stackPopVal1;
		*(outputPoints + i + 1) = stackPopVal2;
	}
}

void seekCoordinate(unsigned char * image, PSTACK inputPoints, int width, int height)
{
	int maxX, minX, maxY, minY;
	//由于C中变量不能在下文声明再使用,故在此先声明.2017年1月19日 add by WJ
	int curPixel[2];
	int stackPopVal1, stackPopVal2;					//用于接收出栈的数据

	//使用带整型节点的数据 替代 C++标准模版中的整型栈 edit by WJ 2017年1月19日
//	STACK_INT points;

//	StackInit(&points);//先初始化一个栈,试分配一下内存,安全起见

	int label = 1;  								// start by 2
	int i, j;

	for (j = 1; j < height - 1; j++)
	{
		for (i = 1; i < width - 1; i++)
		{
			int data = *(image + j*width + i);
			if (data == 1)									//前景像素
			{
				minX = i;
				maxX = minX;
				minY = j;
				maxY = minY;

//				STACK_INT neighborPixels;
//				StackInit(&neighborPixels);
				PSTACK neighborPixels;
				neighborPixels = (PSTACK)malloc(sizeof(STACK_INT));

				StackPush(neighborPixels, j, i);			//将坐标入栈
				++label;  									// 记录第几个前景像素

				/*************************
				 * 查找每个连通域的极大坐标点和极小坐标点
				 * ****************************/
				while (!StackIsEmpty(neighborPixels))
				{
					// get the top pixel on the stack and label it with the same label
					int curX, curY;
					/**curPixel数组已在前方声明,替代pair edit by WJ**/
					curPixel[0] = (*neighborPixels).pTop->data1;
					curPixel[1] = (*neighborPixels).pTop->data2;
					curY = curPixel[0];
					curX = curPixel[1];

					//有问题,需要修改
					*(image + curY*width + curX) = label;			//将连通区域的像素设置为标记号
//					printf("image = %d label = %d (%d,%d)\n",image[curY*width+curX], label, curY, curX);

					//更新边界点,永远取最大边界
					if (maxX < curX) maxX = curX;
					if (minX > curX) minX = curX;
					if (maxY < curY) maxY = curY;
					if (minY > curY) minY = curY;

					// pop the top pixel	像素出栈
					StackPop(neighborPixels, &stackPopVal1, &stackPopVal2);


					// push the 4-neighbors (foreground pixels)		将4领域的前景像素入栈
					if (curX - 1 >= 0 && curX - 1 < width && curY >= 0 && curY < height)		// left pixel
					{
						if (*(image + curY*width + curX - 1) == 1)
						{
							StackPush(neighborPixels, curY, curX - 1);
						}
					}
					if (curX + 1 >= 0 && curX + 1 < width && curY >= 0 && curY < height)		// right pixel
					{
						if (*(image + curY*width + curX + 1) == 1)
						{
							StackPush(neighborPixels, curY, curX + 1);
						}
					}
					if (curX >= 0 && curX < width && curY - 1 >= 0 && curY - 1 < height)		// right pixel
					{
						if (*(image + (curY - 1)*width + curX) == 1)
						{
							StackPush(neighborPixels, curY - 1, curX);
						}
					}
					if (curX >= 0 && curX < width && curY + 1 >= 0 && curY + 1 < height)		// down pixel
					{
						if (*(image + (curY + 1)*width + curX) == 1)
						{
							StackPush(neighborPixels, curY + 1, curX);
						}
					}



				}
				//存入所有的区域坐标
				StackPush(inputPoints, maxX, maxY);//极大点坐标
//				printf("maxX = %d, maxY = %d \n", maxX, maxY);
				StackPush(inputPoints, minX, minY);//极小点坐标
//				printf("minX = %d, minY = %d \n", minX, minY);
				free(neighborPixels);
			}
		}
	}
//	printf("points.size:%d\n", points.size);//edit by WJ//std::cout << points.size() << std::endl;

//	*inputPoints = points;
//	printf("StackTraverse(points) \n");
//	StackTraverse(&points);

	printf("StackTraverse(inputPoints) \n");
	StackTraverse(inputPoints);

//	StackClear(&points);		//释放栈空间

//	printf("StackTraverse(points) \n");
//	StackTraverse(&points);
}


void imagePyrDown(unsigned char * inputImage, unsigned char * outputImage)
{
	int height = 512, width = 656;
	int i,j;

	int temp = 0;
	for (j = 0; j < height; j++)
	{
		if (j % 4 == 0)
		{
			for (i = 0; i < width; i++)
			{
				if (i % 4 == 0)
				{
					temp = *(inputImage + width*j + i);
					*(outputImage + (width/4)*(j / 4) + i / 4) = temp;
				}
				else
				{
					continue;
				}
			}
		}
		else
		{
			continue;
		}
	}
}

void calculateCoordinate(STACK_INT inputPoints ,PSTACK outPoints)
{
//	STACK_INT outputPoints;

	//定义xy变量
	int maxXI, minXI, maxYI, minYI;
	int maxXO, minXO, maxYO, minYO;
	int stackPopVal1, stackPopVal2;

	int times = 4;
	int i = 0;

//	StackInit(&outputPoints);//先初始化一个栈,试分配一下内存,安全起见

	int count = inputPoints.size / 2;		//一个方向上的坐标技数

	for (i = 0; i < count; i++)
	{

		StackPop(&inputPoints, &stackPopVal1, &stackPopVal2);
		maxXI = stackPopVal1;
		maxYI = stackPopVal2;

		StackPop(&inputPoints, &stackPopVal1, &stackPopVal2);
		minXI = stackPopVal1;
		minYI = stackPopVal2;
		printf("in:\n");
		printf("%d,%d\n", maxXI, maxYI);
		printf("%d,%d\n", minXI, minYI);

		//考虑循环越界问题,根据当前坐标,推算原始的边界问题
		if (minXI * times - 1 < 0)
			minXO = 0;
		else
			minXO = minXI * times - 1;

		if (minYI * times - 1<0)
			minYO = 0;
		else
			minYO = minYI * times - 1;

		if (maxXI * times + 1>654)		//640--638	656--654
			maxXO = 654;
		else
			maxXO = maxXI * times + 1;

		if (maxYI * times + 1>510)		//480--478	512--510
			maxYO = 510;
		else
			maxYO = maxYI * times + 1;

		printf("out:\n");
		printf("%d,%d\n", maxXO, maxYO);
		printf("%d,%d\n", minXO, minYO);

		//小区域面积大于某个设定阈值时保存区域坐标
		if ((maxXO - minXO + 1)*(maxYO - minYO + 1) > 20)
		{
			//顺序存储  先(maxXO, maxYO)  后(minXO, minYO)
			StackPush(outPoints, maxXO, maxYO);
			StackPush(outPoints, minXO, minYO);
		}

	}

//	*outPoints = outputPoints;
	printf("StackTraverse(outPoints) \n");
	StackTraverse(outPoints);
//	printf("StackTraverse(outputPoints) \n");
//	StackTraverse(&outputPoints);

//	StackClear(&outputPoints);		//释放栈空间

//	printf("StackTraverse(outPoints) \n");
//	StackTraverse(outPoints);
//	printf("StackTraverse(outputPoints) \n");
//	StackTraverse(&outputPoints);
}

void fastFeaturePointsAndTrack(unsigned char* inputImage,
	int * inputCoordinate,
	int * outputCoordinate,
	int fastThreshold,
	int width,
	int height,
	int *a1,
	double *a2
	)
{

	int cycleTime, tempCycleTime = 0;
	int i, j, k;

	//std::stack<std::pair<int, int>> keyPoints;
	STACK_INT keyPoints;
	StackInit(&keyPoints);//先初始化一个栈,试分配一下内存,安全起见

	int inputCoordinateSize = 0;
	for (i = 0; i < 2000; i++)
	{
		if (inputCoordinate[i] != -1)
		{
			inputCoordinateSize++;
		}
		else
		{
			break;
		}
	}

	cycleTime = inputCoordinateSize / 4;
	//cycleTime = 1;//test
//	printf("cycleTime:%d\n", cycleTime);

	int currentArea;
	//Points_Per_Pixel
	double ppp;

	//遍历单个单个区域的特征
	while (tempCycleTime < cycleTime){

		//取区域坐标
		int maxX, minX, maxY, minY;
		//数组的存储顺序为maxX,maxY,minX,minY
		maxX = inputCoordinate[tempCycleTime * 4 + 0];
		maxY = inputCoordinate[tempCycleTime * 4 + 1];
		minX = inputCoordinate[tempCycleTime * 4 + 2];
		minY = inputCoordinate[tempCycleTime * 4 + 3];

		//判断坐标点是否存在访问越界
		if (minX<3)
		{
			minX = 3;
		}
		if (maxX>height)
		{
			maxX = height - 3;
		}
		if (minY<3)
		{
			minY = 3;
		}
		if (maxY>width)
		{
			maxY = width - 3;
		}

		//计算区域面积
		currentArea = (maxX - minX + 1)*(maxY - minY + 1);
		*a1 = currentArea;

		printf("currentArea:%d \n", currentArea);		//.........................................................

		int xxx = 0;
		for (j = minY; j < maxY; j++)
		{
			for (i = minX; i < maxX; i++)
			{
				int pc = *(inputImage + j*width + i);
				/*
				0:中心点灰度值+TH < 周围点灰度值
				1:中心点灰度值 > 周围点灰度值+TH
				2:其他
				*/
				int check[16], checkFlag[3];
				for (k = 0; k < 16; k++)
				{
				//	int pt;
					if (k == 0){
						/*pt = inputImage.at<uchar>(j - 3, i);*/
						int pt = *(inputImage + (j-3)*width + i);

						if (pc + fastThreshold < pt){
							check[0] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[0] = 1;
						}
						else{
							check[0] = 2;
						}
					}

					if (k == 1){
						/*pt = inputImage.at<uchar>(j - 3, i + 1);*/
						int pt = *(inputImage + (j-3)*width + i+1);

						if (pc + fastThreshold < pt){
							check[1] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 2){
						/*pt = inputImage.at<uchar>(j - 2, i + 2);*/
						int pt = *(inputImage + (j-2)*width + i+2);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 3){
						/*pt = inputImage.at<uchar>(j - 1, i + 3);*/
						int pt = *(inputImage + (j - 1)*width + i + 3);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 4){
						/*pt = inputImage.at<uchar>(j, i + 3);*/
						int pt = *(inputImage + j*width + i + 3);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 5){
						/*pt = inputImage.at<uchar>(j + 1, i + 3);*/
						int pt = *(inputImage + (j + 1)*width + i + 3);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 6){
						/*pt = inputImage.at<uchar>(j + 2, i + 2);*/
						int pt = *(inputImage + (j + 2)*width + i + 2);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 7){
						/*pt = inputImage.at<uchar>(j + 3, i + 1);*/
						int pt = *(inputImage + (j + 3)*width + i + 1);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 8){
						/*pt = inputImage.at<uchar>(j + 3, i);*/
						int pt = *(inputImage + (j + 3)*width + i );

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}
					if (k == 9){
						/*pt = inputImage.at<uchar>(j + 3, i - 1);*/
						int pt = *(inputImage + (j + 3)*width + i -1);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 10){
						/*pt = inputImage.at<uchar>(j + 2, i - 2);*/
						int pt = *(inputImage + (j + 2)*width + i - 2);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 11){
						/*pt = inputImage.at<uchar>(j + 1, i - 3);*/
						int pt = *(inputImage + (j + 1)*width + i - 3);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 12){
						/*pt = inputImage.at<uchar>(j, i - 3);*/
						int pt = *(inputImage + j*width + i - 3);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 13){
						/*pt = inputImage.at<uchar>(j - 1, i - 3);*/
						int pt = *(inputImage + (j - 1)*width + i - 3);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 14){
						/*pt = inputImage.at<uchar>(j - 2, i - 2);*/
						int pt = *(inputImage + (j - 2)*width + i - 2);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					if (k == 15){
						/*pt = inputImage.at<uchar>(j - 3, i - 1);*/
						int pt = *(inputImage + (j - 3)*width + i - 1);

						if (pc + fastThreshold < pt){
							check[k] = 0;
						}
						else if (pc>pt + fastThreshold){
							check[k] = 1;
						}
						else{
							check[k] = 2;
						}
					}

					/*
					0:中心点灰度值+TH < 周围点灰度值
					1:中心点灰度值 > 周围点灰度值+TH
					2:其他
					寻找8连续点
					*/
					checkFlag[0] = 0; checkFlag[1] = 0;
					for (k = 0; k < 25; k++)
					{
						if (k < 16){
							if (check[k] == 0){
								checkFlag[1] = 0;
								checkFlag[0] = checkFlag[0] + 1;
							}
							else if (check[k] == 1){
								checkFlag[0] = 0;
								checkFlag[1] = checkFlag[1] + 1;
							}
							else{
								checkFlag[0] = 0; checkFlag[1] = 0;
							}
						}
						else{
							if (check[k - 16] == 0){
								checkFlag[1] = 0;
								checkFlag[0] = checkFlag[0] + 1;
							}
							else if (check[k - 16] == 1){
								checkFlag[0] = 0;
								checkFlag[1] = checkFlag[1] + 1;
							}
						}

						//判断明暗连续点是否有8个
						if (checkFlag[0] == 8)
						{
							/*keyPoints.push(std::pair<int, int>(i, j));*/
							StackPush(&keyPoints, i, j);
							xxx++;
							break;
						}

					}
				}
			}
		}

//		printf("xxx = %d \n",xxx);
//		ppp = ((double)keyPoints.size) / currentArea;
		ppp = keyPoints.size / (currentArea*1.0);
 		*a2 = ppp;
		printf("ppp:%f \n", ppp);			//.......................................................
		int temp_outputCoordinate = 0;
		if (ppp < 0.1)
		{
			//数组的存储顺序为maxX,maxY,minX,minY
			outputCoordinate[temp_outputCoordinate++] = maxX;
			outputCoordinate[temp_outputCoordinate++] = maxY;
			outputCoordinate[temp_outputCoordinate++] = minX;
			outputCoordinate[temp_outputCoordinate++] = minY;

		}
		//标记出特征点
		while (StackIsEmpty(&keyPoints) == 0)
		{
			int curX, curY;
			curX = keyPoints.pTop->data1;
			curY = keyPoints.pTop->data2;
			int stackPopVal1, stackPopVal2;//用于接收出栈的数据
			*(inputImage + curY*width + curX) = 255;
			StackPop(&keyPoints, &stackPopVal1, &stackPopVal2);
		}


		StackClear(&keyPoints);

		tempCycleTime++;
	}

}
/*************************************************************************/
int main(void)
{
	int i, j, k;
	int width;
	int height;
	int row,col;
	unsigned char *picdata01 = (unsigned char*)0x90000000;
	unsigned char *picdata02 = (unsigned char*)0x90100000;
	unsigned short *bitwidth = (unsigned short *)(picdata01 + 0x00000012);
	unsigned short *bitheight = (unsigned short *)(picdata01 + 0x00000016);

	height = *bitheight;
	width = *bitwidth;
	row = height;
	col = width;

	unsigned char *r1 = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *g1 = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *b1 = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *r2 = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *g2 = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *b2 = (unsigned char *)malloc(width*height*sizeof(unsigned char));

	reader(picdata01, r1, g1, b1, width, height);
	reader(picdata02, r2, g2, b2, width, height);
	/**********************获取背景帧和后续数据帧*************************/
	unsigned char *grey = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *BackGround = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *outpic = (unsigned char *)malloc(3*width*height*sizeof(unsigned char));

	int temp = 0;
	for(i=0;i < row;i++)
	{
		for(j=0;j<col;j++)
		{
			temp = (b1[i*col + j] + g1[i*col + j] + r1[i*col + j])/3;
			BackGround[i*col + j] = temp;
		}
	}

	for(i=0;i < row;i++)
	{
		for(j=0;j<col;j++)
		{
			temp = (b2[i*col + j] + g2[i*col + j] + r2[i*col + j])/3;
			grey[i*col + j] = temp;
		}
	}
	/**********************获取背景帧和后续数据帧*************************/
	unsigned char *diffImage = (unsigned char *)malloc(width*height*sizeof(unsigned char));
	unsigned char *pThreshold = (unsigned char*)malloc(sizeof(unsigned char)*width*height);
	unsigned char *pThresholdPyrDown = (unsigned char*)malloc(sizeof(unsigned char)*width*height / 16);
	unsigned char *pOutput = (unsigned char*)malloc(sizeof(unsigned char)*width*height * 3);

//	int oriPoints[2000], trackCoordinate[2000];
	int *oriPoints = (int *)malloc(2000*sizeof(int));
	int *trackCoordinate = (int *)malloc(2000*sizeof(int));
	int threshold = 20;

	PSTACK points = NULL;
	PSTACK backPoints = NULL;
	points = (PSTACK)malloc(sizeof(STACK_INT));
	backPoints = (PSTACK)malloc(sizeof(STACK_INT));
	GetDiffImage(BackGround, grey, diffImage, width, height);		//获得差分图像
	ImageToThresholdImage(diffImage, pThreshold, width, height, threshold);	//将获得差分图像二值化
	imagePyrDown(pThreshold, pThresholdPyrDown);				//将图像缩小

	seekCoordinate(pThresholdPyrDown, points, width/4, height/4);
	StackTraverse(points);

	calculateCoordinate(*points, backPoints);

	memset(oriPoints, -1, 2000);
	memset(trackCoordinate, -1, 2000);
	stackToArray(*backPoints, oriPoints);

//	StackClear(points);
//	StackClear(backPoints);
	free(points);
	free(backPoints);
//	StackTraverse(points);
//	StackTraverse(backPoints);

	int currentArea;
	double ppp;
	fastFeaturePointsAndTrack(diffImage, oriPoints, trackCoordinate, 10, width, height, &currentArea, &ppp);
	printf("currentArea = %d, ppp = %f \n",currentArea, ppp);
	/*************************************************************/
	int count = 0;
	for (i = 0; i < 2000; i++)
	{
		if (*(trackCoordinate + i) != -1)
			count++;
		else
			break;
	}

	//先全图赋值
	for (j = 0; j < height; j++)
	{
		for (i = 0; i < width; i++)
		{
			pOutput[width*j + i] = 0;
//				*(grey + width*j + i);
			pOutput[width*height + width*j + i] = 0;
//				*(grey + width*j + i);
			pOutput[2*width*height + width*j + i] = 0;
//				*(grey + width*j + i);
		}
	}

	for (k = 0; k < count / 4; k++)
	{
		//取区域坐标
		int maxX, minX, maxY, minY;

		maxX = trackCoordinate[k * 4 + 0];
		maxY = trackCoordinate[k * 4 + 1];
		minX = trackCoordinate[k * 4 + 2];
		minY = trackCoordinate[k * 4 + 3];

		for (j = minY; j < maxY; j++)
		{
			for (i = minX; i < maxX; i++)
			{
				if (*(diffImage + width*j + i) > 10)
				{
					pOutput[width*j + i] = ToBlue(diffImage[width*j + i]) * 5;
					pOutput[width*height + width*j + i] = ToGreen(diffImage[width*j + i]) * 5;
					pOutput[2*width*height + width*j + i] = ToRed(diffImage[width*j + i]) * 5;

				}
			}
		}
	}

	/***********************输出************************/
	unsigned char *outb = (unsigned char *)malloc(3*width*height*sizeof(unsigned char));
	unsigned char *outg = outb + row*col;
	unsigned char *outr = outg + row*col;

	unsigned char*p01 = NULL;
	unsigned char*p02 = NULL;
	unsigned char*p03 = NULL;
	p01 = pOutput;												//b
	p02 = p01 + width*height;												//g
	p03 = p02 + width*height;												//r
	for(i=0;i<height;i++)
	{
		for(j=0; j<width; j++)
		{
			outb[i*col + j] = p01[i*col + j];
			outg[i*col + j] = p02[i*col + j];
			outr[i*col + j] = p03[i*col + j];
		}
	}

	free(b1);
	free(g1);
	free(r1);

	free(b2);
	free(g2);
	free(r2);

	free(grey);
	free(BackGround);
	free(outpic);

	free(oriPoints);
	free(trackCoordinate);

	free(diffImage);
	free(pThreshold);
	free(pThresholdPyrDown);
	free(pOutput);

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月光下的麦克

您的犒赏是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值