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


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

    /**************************************************************
    
    函数功能:对图像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

  • 相关阅读:
    Linux编程make命令(转)
    如何处理Global symbol * requires explicit package name编译错误,以及use strict用法
    6235与旧版本的区别
    Linux下动态链接库的使用
    MTK Socket学习——HTTP请求
    指针和指针的引用
    VC/MFC Combo Box控件的用法
    makefile教程
    常用数据类型使用转换详解
    Linux发送与接收信息
  • 原文地址:https://www.cnblogs.com/hustlx/p/5245573.html
Copyright © 2020-2023  润新知