提取图像里面的红色灯笼(二)

首先对图像进行简单的阈值处理:

/**************************************************************

函数功能:对图像hsi空间红色灯笼的提取

输入参数:源图像src;目标图像des;图像参数width,height,nChannels;

输出参数:目标图像

**************************************************************/

void hsi_seg(unsigned char* des, const unsigned char* src, int width, int height, int nChannels)

{

printf("%d,%d,%d,",nChannels,width,height);

unsigned char* ocl = new unsigned char[width * height * nChannels];

unsigned char* hsi = new unsigned char[width * height * nChannels];

rgb_hsi(hsi,src, width, height, nChannels);//hsi分量提取

for(int y = 0; y < height; y++)

{

for(int x = 0; x < width; x++)

{

int img_H= hsi[y * width * nChannels + x * nChannels ] ;

int img_S= hsi[y * width * nChannels + x * nChannels + 1] ;

int img_I= hsi[y * width * nChannels + x * nChannels + 2] ;

if((img_H<104)&&(img_H>102)&&(img_I>40)&&(img_S>60))

{

//printf("%d, ",img_S);

for(int n=0;n<nChannels;n++)

des[y * width * nChannels + x * nChannels + n] = src[y * width * nChannels + x * nChannels + n] ;

}

else

for(int n=0;n<nChannels;n++)

des[y * width * nChannels + x * nChannels + n] =255;

}

}

ImageDilation(ocl, des, width, height, nChannels,3);//进行3*3的模板膨胀

  

提取红色分量如下图所示,再进行一次3*3模板的膨胀:

clip_image002 clip_image004

再进行一次腐蚀和填充,效果如下:

clip_image006clip_image008

下面是图像填充的代码:

void Imgfill(unsigned char* des, const unsigned char* src, int width, int height, int nChannels)

{

memcpy(des, src, nChannels*width*height);

// TODO: 在此添加命令处理程序代码

//记录填充行的最左位置

int left_X=0;

//记录填充行的最右位置

int right_X=0;

//记录填充列的最上位置

int top_Y=0;

//记录填充列的最下位置

int bottom_Y=0;

//横向填充

for(int y=0;y<height;y++)

{

for(int x=0;x<width-61;x++)

{

int sl=src[y * width * nChannels + x * nChannels + 2];

if(sl!=255)

{

left_X=x;//找到最左边的白色点

for(int k=60;k>0;k--)

{

int sr=src[y * width * nChannels + (x+k) * nChannels + 2];

if(sr!=255)

{

right_X=x+k;

break; //跳出寻找最右边点的循环

}

}

//将left_X与right_X之间的点设置为黑色

for(int x=left_X;x<right_X-1;x++)

{

for(int n=0;n<nChannels;n++)

des[y * width * nChannels + x * nChannels + n]=0;

}

//x=right_X;

//printf("L%d ",left_X);

}

}

}

//纵向填充

for(int x=0;x<width;x++)

{

for(int y=0;y<height-61;y++)

{

int st=src[y * width * nChannels + x * nChannels + 2];

if(255!=st)

{

top_Y=y;//y到最上边的非白色点

for(int m=10;m>0;m--)

{

int sb=src[(y+m) * width * nChannels + x * nChannels + 2];

if(sb!=255)

{

bottom_Y=m+y;

break; //跳出寻找最下边点的循环

}

}

//将top_Y与bottom_Y之间的点设置为黑色

for(int y=top_Y;y<bottom_Y-1;y++)

{

for(int n=0;n<nChannels;n++)

des[y * width * nChannels + x * nChannels + n]=0;

}

}

}

}

}

  

再进行一次8*8的腐蚀和5*5的膨胀:

clip_image010clip_image012

最后重建图像:

clip_image014

二、对大窗户区阴影的增强
/**************************************************************

函数功能:对图像窗户里阴影进行直方图均衡

输入参数:源图像src;目标图像des;图像参数width,height,nChannels;

输出参数:目标图像

**************************************************************/

void win_enhance(unsigned char* des, const unsigned char* src, int width, int height, int nChannels)

{

printf("%d,%d,%d,",nChannels,width,height);

unsigned char* ocl = new unsigned char[width * height * nChannels];

unsigned char* flag = new unsigned char[width * height * nChannels];

int r[256] = {0}, g[256] = {0}, b[256] = {0};

int sum = 0; //图像中像素点的综合

for(int y = 0; y < height; y++)

{

for(int x = 0; x < width; x++)

{

int B= src[y * width * nChannels + x * nChannels ] ;

int G= src[y * width * nChannels + x * nChannels + 1] ;

int R= src[y * width * nChannels + x * nChannels + 2] ;

if((R+G+B<120)&&(y < height-240)&&(y >250))

{

//printf("%d, ",img_S);

for(int n=0;n<nChannels;n++)

{

des[y * width * nChannels + x * nChannels + n] = src[y * width * nChannels + x * nChannels + n] ;

}

}

else

{

for(int n=0;n<nChannels;n++)

{

des[y * width * nChannels + x * nChannels + n] =255;

}

}

}

}

ImageErosion(ocl, des, width, height, nChannels,9);

ImageDilation(des, ocl, width, height, nChannels,10);

  

下图分别为简单的阈值处理后进行一次9*9的腐蚀和10*10膨胀之后的图:

clip_image016clip_image018

下面进行对上图阴影区的直方图均衡:

memcpy(ocl, des,nChannels*width*height);

for(int y=0; y<height; y++)

for(int x=0; x<width; x++)

{

if( des[y * width * nChannels + x * nChannels]!=255)

{

sum=sum+1;

flag[y * width * nChannels + x * nChannels ]= 1;

b[des[y * width * nChannels + x * nChannels + 0]]++;

g[des[y * width * nChannels + x * nChannels + 1]]++;

r[des[y * width * nChannels + x * nChannels + 2]]++;

}

else

{

flag[y * width * nChannels + x * nChannels ]= 0;

}

}

double val[3] = {0};

for(int y=0; y<255; y++)

{

val[0] += b[y];

val[1] += g[y];

val[2] += r[y];

b[y] = val[0]*255/sum;

g[y] = val[1]*255/sum;

r[y] = val[2]*255/sum;

}

for(int y=0; y<height; y++)

for(int x=0; x<width; x++)

{

if(flag[y * width * nChannels + x * nChannels]==1)

{

ocl[y * width * nChannels + x * nChannels + 0] = b[des[y * width * nChannels + x * nChannels + 0]] ;

ocl[y * width * nChannels + x * nChannels + 1] = g[des[y * width * nChannels + x * nChannels + 1]] ;

ocl[y * width * nChannels + x * nChannels + 2] = r[des[y * width * nChannels + x * nChannels + 2]] ;

}

}

//memcpy(des, ocl, nChannels*width*height);

for(int y=0; y<height; y++)

for(int x=0; x<width; x++)

{

if(flag[y * width * nChannels + x * nChannels ]==1)

{

for(int n=0;n<nChannels;n++)

des[y * width * nChannels + x * nChannels + n] = ocl[y * width * nChannels + x * nChannels + n] ;

}

else

{

for(int n=0;n<nChannels;n++)

des[y * width * nChannels + x * nChannels + n] = src[y * width * nChannels + x * nChannels + n] ;

}

}

}

  

最后效果如下:

image

原文地址:https://www.cnblogs.com/hustlx/p/5245573.html