首先对图像进行简单的阈值处理:
/**************************************************************
函数功能:对图像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模板的膨胀:
再进行一次腐蚀和填充,效果如下:
下面是图像填充的代码:
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的膨胀:
最后重建图像:
二、对大窗户区阴影的增强
/**************************************************************
函数功能:对图像窗户里阴影进行直方图均衡
输入参数:源图像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膨胀之后的图:
下面进行对上图阴影区的直方图均衡:
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] ;
}
}
}
最后效果如下: