首先对图像进行简单的阈值处理:
/************************************************************** 函数功能:对图像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] ; } } }
最后效果如下: