📄 segment.cpp
字号:
int pixelByte=nBitCount/8;
//循环变量,遍历像素的每个通道,比如彩色图像三个分量
int k;
//循环变量,用于模板卷积运算
int c, r;
//中间变量
int sum;
//模板卷积运算,边缘像素不处理
for(i=maskH/2;i<height-maskH/2; i++){
for(j=maskW/2; j<width-maskH/2; j++){
//对每个通道数据进行卷积
for(k=0; k<pixelByte; k++){
//卷积求和
sum=0;
for(r=-maskH/2;r<=maskH/2;r++){
for(c=-maskW/2;c<=maskW/2;c++){
sum += *(mask+(r+maskH/2)*maskW+c+maskW/2)
* *(imgIn+(i+r)*lineByte+(j+c)*pixelByte+k);
}
}
//取绝对值
sum=abs(sum);
if(sum>255)
sum=255;
else if(sum<0)
sum=0;
*(imgOut+i*lineByte+j*pixelByte+k)=sum;
}
}
}
}
/***********************************************************************
* 函数名称:
* EdgeByAnyMask()
*
*函数参数:
* int *mask -二维的模板
* int maskW -模板宽
* int maskH -模板高
*
*返回值:
* 无
*
*说明:根据自定义模板检测边缘,同时适合于灰度和彩色图像
***********************************************************************/
void ImgSegment::EdgeByAnyMask(int *mask ,int maskW, int maskH)
{
//释放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];
//模板卷积函数调用
TemplateEdge(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
mask, maskW, maskH, m_pImgDataOut);
}
/***********************************************************************
* 函数名称:
* Krisch()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:Krisch边缘检测,同时适合于灰度和彩色图像
***********************************************************************/
void ImgSegment::Krisch()
{
//释放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];
//输出图像缓冲区初始化为0
memset(m_pImgDataOut, 0, lineByte*m_imgHeight);
//循环变量,图像的坐标
int i,j;
//每像素占字节数,输出图像与输入图像相同
int pixelByte=m_nBitCount/8;
//循环变量,遍历像素的每个通道,比如彩色图像三个分量
int k;
//两个指针变量
unsigned char *p1, *p2;
//申请临时缓冲区,存放中间结果
unsigned char *buf=new unsigned char[lineByte* m_imgHeight];
//模板数组
int mask[9];
// 设置Kirsch模板1参数
mask[0] = 5;
mask[1] = 5;
mask[2] = 5;
mask[3] = -3;
mask[4] = 0;
mask[5] = -3;
mask[6] = -3;
mask[7] = -3;
mask[8] = -3;
//模板卷积函数调用
TemplateEdge(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
mask, 3, 3, buf);
//求两幅缓存图像的最大值,并将大的值存入m_pImgDataOut中
for(i=0;i<m_imgHeight;i++){
for(j=0;j<m_imgWidth;j++){
for(k=0;k<pixelByte;k++){
p1=m_pImgDataOut+i*lineByte+j*pixelByte+k;
p2=buf+i*lineByte+j*pixelByte+k;
if(*p1<*p2)
*p1=*p2;
}
}
}
// 设置Kirsch模板2参数
mask[0] = -3;
mask[1] = 5;
mask[2] = 5;
mask[3] = -3;
mask[4] = 0;
mask[5] = 5;
mask[6] = -3;
mask[7] = -3;
mask[8] = -3;
//模板卷积函数调用
TemplateEdge(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
mask, 3, 3, buf);
//求两幅缓存图像的最大值,并将大的值存入m_pImgDataOut中
for(i=0;i<m_imgHeight;i++){
for(j=0;j<m_imgWidth;j++){
for(k=0;k<pixelByte;k++){
p1=m_pImgDataOut+i*lineByte+j*pixelByte+k;
p2=buf+i*lineByte+j*pixelByte+k;
if(*p1<*p2)
*p1=*p2;
}
}
}
// 设置Kirsch模板3参数
mask[0] = -3;
mask[1] = -3;
mask[2] = 5;
mask[3] = -3;
mask[4] = 0;
mask[5] = 5;
mask[6] = -3;
mask[7] = -3;
mask[8] = 5;
//模板卷积函数调用
TemplateEdge(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
mask, 3, 3, buf);
//求两幅缓存图像的最大值,并将大的值存入m_pImgDataOut中
for(i=0;i<m_imgHeight;i++){
for(j=0;j<m_imgWidth;j++){
for(k=0;k<pixelByte;k++){
p1=m_pImgDataOut+i*lineByte+j*pixelByte+k;
p2=buf+i*lineByte+j*pixelByte+k;
if(*p1<*p2)
*p1=*p2;
}
}
}
// 设置Kirsch模板4参数
mask[0] = -3;
mask[1] = -3;
mask[2] = -3;
mask[3] = -3;
mask[4] = 0;
mask[5] = 5;
mask[6] = -3;
mask[7] = 5;
mask[8] = 5;
//模板卷积函数调用
TemplateEdge(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
mask, 3, 3, buf);
//求两幅缓存图像的最大值,并将大的值存入m_pImgDataOut中
for(i=0;i<m_imgHeight;i++){
for(j=0;j<m_imgWidth;j++){
for(k=0;k<pixelByte;k++){
p1=m_pImgDataOut+i*lineByte+j*pixelByte+k;
p2=buf+i*lineByte+j*pixelByte+k;
if(*p1<*p2)
*p1=*p2;
}
}
}
// 设置Kirsch模板5参数
mask[0] = -3;
mask[1] = -3;
mask[2] = -3;
mask[3] = -3;
mask[4] = 0;
mask[5] = -3;
mask[6] = 5;
mask[7] = 5;
mask[8] = 5;
//模板卷积函数调用
TemplateEdge(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount, mask, 3, 3, buf);
//求两幅缓存图像的最大值,并将大的值存入m_pImgDataOut中
for(i=0;i<m_imgHeight;i++){
for(j=0;j<m_imgWidth;j++){
for(k=0;k<pixelByte;k++){
p1=m_pImgDataOut+i*lineByte+j*pixelByte+k;
p2=buf+i*lineByte+j*pixelByte+k;
if(*p1<*p2)
*p1=*p2;
}
}
}
// 设置Kirsch模板6参数
mask[0] = -3;
mask[1] = -3;
mask[2] = -3;
mask[3] = 5;
mask[4] = 0;
mask[5] = -3;
mask[6] = 5;
mask[7] = 5;
mask[8] = -3;
//模板卷积函数调用
TemplateEdge(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
mask, 3, 3, buf);
//求两幅缓存图像的最大值,并将大的值存入m_pImgDataOut中
for(i=0;i<m_imgHeight;i++){
for(j=0;j<m_imgWidth;j++){
for(k=0;k<pixelByte;k++){
p1=m_pImgDataOut+i*lineByte+j*pixelByte+k;
p2=buf+i*lineByte+j*pixelByte+k;
if(*p1<*p2)
*p1=*p2;
}
}
}
// 设置Kirsch模板7参数
mask[0] = 5;
mask[1] = -3;
mask[2] = -3;
mask[3] = 5;
mask[4] = 0;
mask[5] = -3;
mask[6] = 5;
mask[7] = -3;
mask[8] = -3;
//模板卷积函数调用
TemplateEdge(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
mask, 3, 3, buf);
//求两幅缓存图像的最大值,并将大的值存入m_pImgDataOut中
for(i=0;i<m_imgHeight;i++){
for(j=0;j<m_imgWidth;j++){
for(k=0;k<pixelByte;k++){
p1=m_pImgDataOut+i*lineByte+j*pixelByte+k;
p2=buf+i*lineByte+j*pixelByte+k;
if(*p1<*p2)
*p1=*p2;
}
}
}
// 设置Kirsch模板8参数
mask[0] = 5;
mask[1] = 5;
mask[2] = -3;
mask[3] = 5;
mask[4] = 0;
mask[5] = -3;
mask[6] = -3;
mask[7] = -3;
mask[8] = -3;
//模板卷积函数调用
TemplateEdge(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount,
mask, 3, 3, buf);
//求两幅缓存图像的最大值,并将大的值存入m_pImgDataOut中
for(i=0;i<m_imgHeight;i++){
for(j=0;j<m_imgWidth;j++){
for(k=0;k<pixelByte;k++){
if(*(m_pImgDataOut+i*lineByte+j*pixelByte+k)<*(buf+i*lineByte+j*pixelByte+k))
*(m_pImgDataOut+i*lineByte+j*pixelByte+k)=*(buf+i*lineByte+j*pixelByte+k);
}
}
}
}
/***********************************************************************
* 函数名称:
* GaussLaplacian()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:Gauss-Laplacian边缘检测,同时适合于灰度和彩色图像
***********************************************************************/
void ImgSegment::GaussLaplacian()
{
//定义Gauss-Laplacian模板
int mask[25];
mask[0] = -2;
mask[1] = -4;
mask[2] = -4;
mask[3] = -4;
mask[4] = -2;
mask[5] = -4;
mask[6] = 0;
mask[7] = 8;
mask[8] = 0;
mask[9] = -4;
mask[10] = -4;
mask[11] = 8;
mask[12] = 24;
mask[13] = 8;
mask[14] = -4;
mask[15] = -4;
mask[16] = 0;
mask[17] = 8;
mask[18] = 0;
mask[19] = -4;
mask[20] = -2;
mask[21] = -4;
mask[22] = -4;
mask[23] = -4;
mask[24] = -2;
//释放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];
//模板卷积函数调用
TemplateEdge(m_pImgData, m_imgWidth, m_imgHeight, m_nBitCount, mask, 5, 5, m_pImgDataOut);
}
/***********************************************************************
* 函数名称:
* HoughTransform()
*
*函数参数:
* unsigned char *imgBinaryIn -二值图像输入数据指针
* int width -图像的 宽
* int height -图像的高
* int *houghBuf -Hough变换所需要的缓冲区指针
* int houghWidth -Hough变换缓冲区的宽
* int houghHeight -Hough变换缓冲区的高
* float radiusResolution -Hough变换的极坐标半径的检测分辨率
* float angleResolution -Hough变换的角度检测分辨率
* float *radius -用来返回Hough变换检测出来的最长直线的极半径
* float *angle -用来返回Hough变换检测出来的最长直线的角度
*返回值:
* 无
*
*说明:给定图像数据,通过线检测hough变换检测直线
***********************************************************************/
void ImgSegment::HoughTransform(unsigned char *imgBinaryIn, int width,
int height, int *houghBuf, int houghWidth, int houghHeight,
float radiusResolution, float angleResolution,
float *radius, float *angle)
{
//申请循环变量
int i, j;
//清理变换空间累加数组
for(i=0;i<houghHeight;i++){
for(j=0;j<houghWidth;j++){
*(houghBuf+i*houghWidth+j)=0;
}
}
//循环变量
int r, a;
//中间变量
float tempR, tempA;
//遍历图像数据
for(i=0;i<height;i++){
for(j=0;j<width;j++){
//出现一个目标点
if(*(imgBinaryIn+i*width+j)==0){
//a代表角度的循环变量,在变换空间累加数组的垂直方向上
for(a=0;a<houghHeight;a++){
//按照给定变换角度的分辨率,求取角度
tempA=(a-houghHeight/2)*angleResolution;
//根据当前遍历的角度及x,y值求取对应极半径
tempR=(j-width/2)*cos(tempA*2*3.1415926/360)+(i-height/2)*sin(tempA*2*3.1415926/360);
r=tempR/radiusResolution;
//累加数组累加
*(houghBuf+a*houghWidth+ r+houghWidth/2)+=1;
}
}
}
}
//求累加数组的极大值,并记录此时的数组坐标
int max, maxR, maxA;
max=*(houghBuf+0*houghWidth+0);
maxR=0;
maxA=0;
for(a=0;a<houghHeight;a++){
for(r=0;r<houghWidth;r++){
if(max<=*(houghBuf+a*houghWidth+r)){
max=*(houghBuf+a*houghWidth+r);
maxR=r;
maxA=a;
}
}
}
//将极大值位置转换成极坐标半径和角度,并通过参数返回
*radius=(maxR-houghWidth/2)*radiusResolution;
*angle=(maxA-houghHeight/2)*angleResolution;
}
/***********************************************************************
* 函数名称:
* Hough()
*
*函数参数:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -