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

📄 segment.cpp

📁 将数字图像处理的一般算法都集中在一个MFC的框架中
💻 CPP
📖 第 1 页 / 共 3 页
字号:
*  float radiusResolution  -Hough变换的极坐标半径的检测分辨率
*  float angleResolution  -Hough变换的角度检测分辨率 
*  float *radius  -用来返回Hough变换检测出来的最长直线的极半径
*  float *angle   -用来返回Hough变换检测出来的最长直线的角度

*返回值:
*   无
*
*说明:给定Hough变换的极半径分辨率和角度分辨率,通过调用HoughTransform()
*      对输入图像m_pImgData做线检测,Hough变换的结果输出到m_pImgDataOut中
***********************************************************************/
void ImgSegment::Hough(float radiusResolution, float angleResolution,
					   float *radius, float *angle)
{
	//只处理灰度图像
	if(m_nBitCount!=8)
		return;

	//释放缓冲区
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
    	m_pImgDataOut=NULL;
	}
	if(m_lpColorTableOut!=NULL){
		delete []m_lpColorTableOut;
		m_lpColorTableOut=NULL;
	}

	//输出图像的每像素位数及颜色表长度
	m_nBitCountOut=m_nBitCount;
	m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut);

	//输出图像颜色表与输入图像相同
	if(m_nColorTableLengthOut!=0){
    	m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut];
		memcpy(m_lpColorTableOut,m_lpColorTable,
			sizeof(RGBQUAD)*m_nColorTableLengthOut);
	}
	

	//图像的中心为坐标原点,线与原点的距离最大
	//为sqrt(m_imgWidth*m_imgWidth+m_imgHeight*m_imgHeight)/2,所以Hough变换
	//的高度为:
	int houghWidth=sqrt(m_imgWidth*m_imgWidth+m_imgHeight*m_imgHeight);
	 houghWidth /= radiusResolution;

	//线的角度在[-90,90]之间,所以申请的累加数组高度为181/angleResolution
	int houghHeight=181/angleResolution;

	//申请累加数组缓冲区
	int *houghBuf=new int[houghWidth*houghHeight];

	//Hough变换,结果存入houghBuf中
	HoughTransform(m_pImgData, m_imgWidth, m_imgHeight, houghBuf,  houghWidth,
	        	houghHeight,radiusResolution, angleResolution, radius, angle);
	
	//输出图像的大小是Hough变换累加数组的大小			
	m_imgWidthOut=houghWidth;
	m_imgHeightOut=houghHeight;
	int lineByteOut=(m_imgWidthOut*m_nBitCountOut/8+3)/4*4;
	m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeightOut];

	//求出累加数组的最大值
	int i, j, max=0; 
	for(i=0;i<m_imgHeightOut;i++){
		for(j=0;j<m_imgWidthOut;j++){
			if(max<=*(houghBuf+i*houghWidth+j))
				max=*(houghBuf+i*houghWidth+j);
		}
	}
	//根据最大值将累加数组映射到输出图像
	for(i=0;i<m_imgHeightOut;i++){
		for(j=0;j<m_imgWidthOut;j++){
			*(m_pImgDataOut+i*lineByteOut+j)=
				*(houghBuf+i*houghWidth+j)*255.0/max;
		}
	}
	
	//释放缓冲区
	delete []houghBuf;
}

/***********************************************************************
* 函数名称:
* longestLineDetectByHough()
*
*函数参数:
*  float radiusResolution  -Hough变换的极坐标半径的检测分辨率
*  float angleResolution  -Hough变换的角度检测分辨率 
*  float *radius  -用来返回Hough变换检测出来的最长直线的极半径
*  float *angle   -用来返回Hough变换检测出来的最长直线的角度

*返回值:
*   无
*
*说明:给定Hough变换的极半径分辨率和角度分辨率,通过调用HoughTransform()
*      对输入图像m_pImgData做线检测,根据最长线的角度和极坐标半径,将最
*     长线输出到m_pImgDataOut中
***********************************************************************/
void ImgSegment::longestLineDetectByHough(float radiusResolution, float angleResolution)
{
	//只处理灰度图像
	if(m_nBitCount!=8)
		return;

	//释放缓冲区
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
    	m_pImgDataOut=NULL;
	}
	if(m_lpColorTableOut!=NULL){
		delete []m_lpColorTableOut;
		m_lpColorTableOut=NULL;
	}

	//输出图像的每像素位数及颜色表长度
	m_nBitCountOut=m_nBitCount;
	m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut);

	//输出图像颜色表与输入图像相同
	if(m_nColorTableLengthOut!=0){
    	m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut];
		memcpy(m_lpColorTableOut,m_lpColorTable,
			sizeof(RGBQUAD)*m_nColorTableLengthOut);
	}
	

	//图像的中心为坐标原点,线与原点的距离最大
	//为sqrt(m_imgWidth*m_imgWidth+m_imgHeight*m_imgHeight)/2,所以Hough变换
	//的高度为:
	int houghWidth=sqrt(m_imgWidth*m_imgWidth+m_imgHeight*m_imgHeight);
	 houghWidth /= radiusResolution;

	//线的角度在[-90,90]之间,所以申请的累加数组高度为181/angleResolution
	int houghHeight=181/angleResolution;

	//申请累加数组缓冲区
	int *houghBuf=new int[houghWidth*houghHeight];

	//Hough变换,结果存入houghBuf中
	float radius, angle;
	HoughTransform(m_pImgData, m_imgWidth, m_imgHeight, houghBuf,  houghWidth,
	        	houghHeight,radiusResolution, angleResolution, &radius, &angle);

	//输出图像的大小与输入图像相同
	m_imgWidthOut=m_imgWidth;
	m_imgHeightOut=m_imgHeight;
	int lineByteOut=(m_imgWidthOut*m_nBitCountOut/8+3)/4*4;
	m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeightOut];

	//根据求得的角度和极坐标半径,在白色背景下画出最长直线并作为输出图像显示
	memset(m_pImgDataOut,255,lineByteOut*m_imgHeightOut);

	//angle的单位是度,此处转换为弧度进行计算
	float alfa=angle*2*3.1415926/360;

	
	int x, y, i, j;
	for( x=-m_imgWidthOut/2;x<m_imgWidthOut/2;x++){
		//图像的中心位置为坐标原点,(x,y)为直角坐标系中的点,
		//将其转换至坐标原点在图像左下角的坐标系(i,j)
		y=radius/sin(alfa)-x/tan(alfa);
		j=x-m_imgWidthOut/2;
		i=y+m_imgHeightOut/2;
		if(i>0&&i<m_imgHeightOut)
	    	*(m_pImgDataOut+i*m_imgWidthOut+j)=0;
	}

	//空间释放
	delete []houghBuf;
}



/***********************************************************************
* 函数名称:
* RegionGrow()
*
*函数参数:
*  CPoint seed  -种子点
*  int thresh   -阈值
*
*返回值:
*   无
*
*说明:区域生长算法,给定一个种子点seed和阈值thresh,从种子点处开始生长,
*      将与种子点像素灰度值之差thresh的像素合并在一起形成一个区域,该函
*      数只处理灰度图像
***********************************************************************/
void ImgSegment::RegionGrow(CPoint seed, int thresh)
{
	//只处理灰度图像
	if(m_nBitCount!=8)
		return;

	//释放m_pImgDataOut指向的图像数据空间
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
    	m_pImgDataOut=NULL;
	}
	//释放颜色表空间
	if(m_lpColorTableOut!=NULL){
		delete []m_lpColorTableOut;
		m_lpColorTableOut=NULL;
	}

	//输出图像与输入图像为同一类型
	m_nBitCountOut=m_nBitCount;

	//输出图像颜色表长度
	m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut);

	//输出图像颜色表,与输入图像相同
	if(m_nColorTableLengthOut!=0){
    	m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut];
		memcpy(m_lpColorTableOut,m_lpColorTable,
			     sizeof(RGBQUAD)*m_nColorTableLengthOut);
	}

	//输出图像的宽高,与输入图像相等
	m_imgWidthOut=m_imgWidth;
	m_imgHeightOut=m_imgHeight;

	//每行像素所占字节数,输出图像与输入图像相同
	int lineByte=(m_imgWidth*m_nBitCount/8+3)/4*4;

	//申请输出图像缓冲区
	m_pImgDataOut=new unsigned char[lineByte*m_imgHeight];

	//以下是区域生长代码

	//循环变量
	int i, j;

	//将输出图像初始化置255,用0代表像素的生长标记
	for(i=0;i<m_imgHeight;i++){
		for(j=0;j<m_imgWidth;j++){
			*(m_pImgDataOut+i*lineByte+j)=255;
		}
	}

	//二维数组direction代表中心像素点8邻域坐标与该点在x和y方向上的偏移,
	//其中第一列为x方向的偏移,第二列为y方向的偏移
	int direction[8][2]={{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};

	//栈申请,此处假定进栈的像素最多为图像总像素数
	CPoint *stack=new CPoint[m_imgWidth*m_imgHeight];

	//栈顶指针
	int top;

	//当前正处理的点和弹出的点
	CPoint currentPoint, popPoint;

	//循环变量,遍历array数组的第一维下标
	int k;

	//标记变量
	int label;

	//临时变量
	int temp1, temp2;

	//记录种子像素的灰度值
	temp1=*(m_pImgData+seed.y*lineByte+seed.x);

	//将给定种子点置标记0,入栈
	*(m_pImgDataOut+seed.y*lineByte+seed.x)=0;
	top=0;
	stack[top].x=seed.x;
	stack[top].y=seed.y;

	//堆栈
	while(top>-1){
		//弹出栈顶元素,该元素已经生长过
		popPoint.x=stack[top].x;
		popPoint.y=stack[top].y;
		top--;

		//考察弹出像素周围是否有没有生长的像素
		for(k=0;k<8;k++){

			//待考察的邻域点
			currentPoint.x=popPoint.x+direction[k][0];
			currentPoint.y=popPoint.y+direction[k][1];

			//如果待考察的点不在图像内,则跳过
			if(currentPoint.x<0||currentPoint.x>m_imgWidth-1||
				currentPoint.y<0||currentPoint.y>m_imgHeight-1)
				continue;
			
			//该点标号
			label=*(m_pImgDataOut+currentPoint.y*lineByte+currentPoint.x);

			//弹出的点周围有尚没生长的点
			if(label==255){
				temp2=*(m_pImgData+currentPoint.y*lineByte+currentPoint.x);
				//如果当前被考察的像素灰度值与种子点灰度值之差小于给定的阈值,
				//则认为相似,将其进栈处理
				if(abs(temp1-temp2)<thresh){
					//给该点置生长标记0
					*(m_pImgDataOut+currentPoint.y*lineByte+currentPoint.x)=0;
					top++;
					stack[top].x=currentPoint.x;
					stack[top].y=currentPoint.y;
				}
			}
		}
		
	}
	
	//清除缓冲区
	delete []stack;
}



/***********************************************************************
* 函数名称:
* ContourExtract()
*
*函数参数:
*  无
*
*返回值:
*   无
*
*说明:给定一个二值图像,把黑色区域看作目标,白色看作背景,提取目标的轮廓
***********************************************************************/
void ImgSegment::ContourExtract()
{
	//只处理灰度图像
	if(m_nBitCount!=8)
		return;

	//释放m_pImgDataOut指向的图像数据空间
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
    	m_pImgDataOut=NULL;
	}
	//释放颜色表空间
	if(m_lpColorTableOut!=NULL){
		delete []m_lpColorTableOut;
		m_lpColorTableOut=NULL;
	}

	//输出图像与输入图像为同一类型
	m_nBitCountOut=m_nBitCount;

	//输出图像颜色表长度
	m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut);

	//输出图像颜色表,与输入图像相同
	if(m_nColorTableLengthOut!=0){
    	m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut];
		memcpy(m_lpColorTableOut,m_lpColorTable,sizeof(RGBQUAD)*m_nColorTableLengthOut);
	}

	//输出图像的宽高,与输入图像相等
	m_imgWidthOut=m_imgWidth;
	m_imgHeightOut=m_imgHeight;

	//每行像素所占字节数,输出图像与输入图像相同
	int lineByte=(m_imgWidth*m_nBitCount/8+3)/4*4;

	//申请输出图像缓冲区
	m_pImgDataOut=new unsigned char[lineByte*m_imgHeight];

	//以下是轮廓提取代码

	//将输入图像数据拷贝置输出图像缓冲区
	memcpy(m_pImgDataOut,m_pImgData,lineByte*m_imgHeight);

	//存放黑点像素8邻域的像素灰度值
	int array[8];

	//数组求和
	int sum;

	//循环变量
	int i, j, k;

	//搜索图像中的黑点,不考虑边界上的点
	for(i=1;i<m_imgHeight-1;i++){
		for(j=1;j<m_imgWidth-1;j++){
			//找到一个黑点
			if(*(m_pImgData+i*lineByte+j)==0){
				//拷贝周围8邻域像素进array数组
		    	array[0]=*(m_pImgData+i*lineByte+j+1);
				array[1]=*(m_pImgData+(i+1)*lineByte+j+1);
				array[2]=*(m_pImgData+(i+1)*lineByte+j);
				array[3]=*(m_pImgData+(i+1)*lineByte+j-1);
				array[4]=*(m_pImgData+i*lineByte+j-1);
				array[5]=*(m_pImgData+(i-1)*lineByte+j-1);
				array[6]=*(m_pImgData+(i-1)*lineByte+j);
				array[7]=*(m_pImgData+(i-1)*lineByte+j+1);
				
				//对数组求和
				sum=0;
				for(k=0;k<8;k++)
					sum += array[k];

				//周围8邻域均为黑点,则输出图像对应像素置白色
				if(sum==0)
				   *(m_pImgDataOut+i*lineByte+j)=255;
				
			}
		}
	}

}

/***********************************************************************
* 函数名称:
* ContourTrace()
*
*函数参数:
*  无
*
*返回值:
*   无
*
*说明:给定一个二值图像,把黑色区域看作目标,白色看作背景,跟踪目标的边界
***********************************************************************/
void ImgSegment::ContourTrace()
{
	//只处理灰度图像
	if(m_nBitCount!=8)
		return;

	//释放m_pImgDataOut指向的图像数据空间
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
    	m_pImgDataOut=NULL;
	}
	//释放颜色表空间
	if(m_lpColorTableOut!=NULL){
		delete []m_lpColorTableOut;
		m_lpColorTableOut=NULL;
	}

	//输出图像与输入图像为同一类型
	m_nBitCountOut=m_nBitCount;

	//输出图像颜色表长度
	m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut);

	//输出图像颜色表,与输入图像相同
	if(m_nColorTableLengthOut!=0){
    	m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut];
		memcpy(m_lpColorTableOut,m_lpColorTable,
			           sizeof(RGBQUAD)*m_nColorTableLengthOut);
	}

	//输出图像的宽高,与输入图像相等
	m_imgWidthOut=m_imgWidth;
	m_imgHeightOut=m_imgHeight;

	//每行像素所占字节数,输出图像与输入图像相同
	int lineByte=(m_imgWidth*m_nBitCount/8+3)/4*4;

	//申请输出图像缓冲区
	m_pImgDataOut=new unsigned char[lineByte*m_imgHeight];

	//将输出图像初始化置255,用0代表轮廓像素标记
	memset(m_pImgDataOut,255,lineByte*m_imgHeight);

	//顺时针定义中心像素点的8邻域坐标,第一列为x方向的偏移,第二列为y方向的偏移
	int direction[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};

	//边界起始点,待处理的当前点,当前点的邻域点
	CPoint startP, currentP, neighborP;

	//是否当前点与起始边界点重合的标志变量
	int findStartPoint;

	//搜索边界起始点
	findStartPoint=0;

	//循环变量,图像坐标
	int i,j;
	for(i=0;i<m_imgHeight;i++){
		for(j=0;j<m_imgWidth;j++){
			//找到起始边界点
			if(*(m_pImgData+i*lineByte+j)==0){
				startP.x=j;
				startP.y=i;
				*(m_pImgDataOut+i*lineByte+j)=0;
				findStartPoint=1;
				break;
			}
		}

		//已经找到起始边界点
		if(findStartPoint)
			break;
	}

	//边界跟踪
	//从初始点开始跟踪
	currentP.x=startP.x;
	currentP.y=startP.y;

	//邻域点是否边界点标志变量
	int isContourP;

	//开始方向
	int startDirect=0;

	//0表示还没有返回最初的边界起始点
	findStartPoint=0;
	while(findStartPoint==0){
		isContourP=false;
		while(isContourP==false){
			neighborP.x=currentP.x+direction[startDirect][0];
			neighborP.y=currentP.y+direction[startDirect][1];

			//搜索到邻域点
			if(*(m_pImgData+neighborP.y*lineByte+neighborP.x)==0){
				isContourP=true;
				currentP.x=neighborP.x;
				currentP.y=neighborP.y;

				if(currentP.x==startP.x&&currentP.y==startP.y)
					findStartPoint=true;//回到边界起始点了

				*(m_pImgDataOut+currentP.y*lineByte+currentP.x)=0;

				//扫描方向逆时针旋转90度
				startDirect-=2;
				if(startDirect<0)
					startDirect+=8;
			}
			else{
				//扫描方向顺时针旋转45度
				startDirect++;
				if(startDirect==8)
					startDirect=0;
			}

		}
	}
	
}

⌨️ 快捷键说明

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