zoukankan      html  css  js  c++  java
  • 图像增强

    Mat ImageAHE(Mat img, int block)
    {
        Mat AHE_GO = img.clone();
    
        int width = img.cols;
        int height = img.rows;
        int width_block = width / block; //每个小格子的长和宽
        int height_block = height / block;
        //存储各个直方图
    
    
        int tmp2[16 * 16][256] = { 0 };//10要和block保持一致
        float C2[16 * 16][256] = { 0.0 };
        //分块
        int total = width_block * height_block;//分割的总的块儿数
        for (int i = 0; i < block; i++)
        {
            for (int j = 0; j < block; j++)
            {
                int start_x = i * width_block;
                int end_x = start_x + width_block;
                int start_y = j * height_block;
                int end_y = start_y + height_block;
    
                int num = i + block * j;
                //遍历小块,计算直方图
                for (int ii = start_x; ii < end_x; ii++)
                {
                    for (int jj = start_y; jj < end_y; jj++)
                    {
                        int index = img.at<uchar>(jj, ii);
                        tmp2[num][index]++;
                    }
                }
                //计算累积分布直方图
                for (int k = 0; k < 256; k++)
                {
                    if (k == 0)
                        C2[num][k] = 1.0f * tmp2[num][k] / total;
                    else
                        C2[num][k] = C2[num][k - 1] + 1.0f * tmp2[num][k] / total;
                }
            }
        }
        //将统计结果写入
        for (int i = 0; i < block; i++)
        {
            for (int j = 0; j < block; j++)
            {
                int start_x = i * width_block;
                int end_x = start_x + width_block;
                int start_y = j * height_block;
                int end_y = start_y + height_block;
                int num = i + block * j;
                //遍历小块,计算直方图
                for (int ii = start_x; ii < end_x; ii++)
                {
                    for (int jj = start_y; jj < end_y; jj++)
                    {
                        int index = img.at<uchar>(jj, ii);
                        //结果直接写入AHE_GO中去
                        AHE_GO.at<uchar>(jj, ii) = C2[num][index] * 255;
                    }
                }
            }
        }
        return AHE_GO;
    }
    
    Mat ImageEqaualize(Mat img)
    {
        int width = img.cols;
        int height = img.rows;
        Mat HT_GO = img.clone();
        int tmp[256] = { 0 };
        float C[256] = { 0.0 };
        int total = width * height;
        for (int i = 0; i < img.rows; i++)
        {
            for (int j = 0; j < img.cols; j++)
            {
                int index = img.at<uchar>(i, j);
                tmp[index] ++;
            }
        }
        //计算累积函数
        for (int i = 0; i < 256; i++) {
            if (i == 0)
                C[i] = 1.0f * tmp[i] / total;
            else
                C[i] = C[i - 1] + 1.0f * tmp[i] / total;
        }
        //这里的累积函数分配的方法非常直观高效
        for (int i = 0; i < img.rows; i++) {
            for (int j = 0; j < img.cols; j++) {
                int index = img.at<uchar>(i, j);
                HT_GO.at<uchar>(i, j) = C[index] * 255;
            }
        }
        return HT_GO;
    }
    
    Mat ImageClHe(Mat img, int block)
    {
        int width = img.cols/ block;
        int height = img.rows/ block;
        Mat CLHE_GO = img.clone();
        int tmp[256] = { 0 };
        float C[256] = { 0.0 };
        int total = width * height;
        for (int i = 0; i < img.rows; i++)
        {
            for (int j = 0; j < img.cols; j++)
            {
                int index = img.at<uchar>(i, j);
                tmp[index] ++;
            }
        }
        /////////////////////////限制对比度计算部分,注意这个地方average的计算不一定科学
        int average = width * height / 255 /64;
        int LIMIT = 4 * average;
        int steal = 0;
        for (int k = 0; k < 256; k++)
        {
            if (tmp[k] > LIMIT) {
                steal += tmp[k] - LIMIT;
                tmp[k] = LIMIT;
            }
        }
        int bonus = steal / 256;
        //hand out the steals averagely
        for (int k = 0; k < 256; k++)
        {
            tmp[k] += bonus;
        }
        ///////////////////////////////////////////
        //计算累积函数
        for (int i = 0; i < 256; i++) {
            if (i == 0)
                C[i] = 1.0f * tmp[i] / total;
            else
                C[i] = C[i - 1] + 1.0f * tmp[i] / total;
        }
        //这里的累积函数分配的方法非常直观高效
        for (int i = 0; i < img.rows; i++) {
            for (int j = 0; j < img.cols; j++) {
                int index = img.at<uchar>(i, j);
                CLHE_GO.at<uchar>(i, j) = C[index] * 255;
            }
        }
        return CLHE_GO;
    }
    
    Mat ImageClHeNoInter(Mat img, int block)
    {
        Mat CLAHE_GO = img.clone();
    
        int width = img.cols;
        int height = img.rows;
        int width_block = width / block; //每个小格子的长和宽
        int height_block = height / block;
        //存储各个直方图
        int tmp2[8 * 8][256] = { 0 };
        float C2[8 * 8][256] = { 0.0 };
        //分块
        int total = width_block * height_block;
        for (int i = 0; i < block; i++)
        {
            for (int j = 0; j < block; j++)
            {
                int start_x = i * width_block;
                int end_x = start_x + width_block;
                int start_y = j * height_block;
                int end_y = start_y + height_block;
                int num = i + block * j;
                //遍历小块,计算直方图
                for (int ii = start_x; ii < end_x; ii++)
                {
                    for (int jj = start_y; jj < end_y; jj++)
                    {
                        int index = img.at<uchar>(jj, ii);
                        tmp2[num][index]++;
                    }
                }
                //裁剪和增加操作,也就是clahe中的cl部分
                //这里的参数 对应《Gem》上面 fCliplimit  = 4  , uiNrBins  = 255
                int average = width_block * height_block / 255;
                int LIMIT = 4 * average;
                int steal = 0;
                for (int k = 0; k < 256; k++)
                {
                    if (tmp2[num][k] > LIMIT) {
                        steal += tmp2[num][k] - LIMIT;
                        tmp2[num][k] = LIMIT;
                    }
                }
                int bonus = steal / 256;
                //hand out the steals averagely
                for (int k = 0; k < 256; k++)
                {
                    tmp2[num][k] += bonus;
                }
                //计算累积分布直方图
                for (int k = 0; k < 256; k++)
                {
                    if (k == 0)
                        C2[num][k] = 1.0f * tmp2[num][k] / total;
                    else
                        C2[num][k] = C2[num][k - 1] + 1.0f * tmp2[num][k] / total;
                }
            }
        }
        //计算变换后的像素值
        //将统计结果写入
        for (int i = 0; i < block; i++)
        {
            for (int j = 0; j < block; j++)
            {
                int start_x = i * width_block;
                int end_x = start_x + width_block;
                int start_y = j * height_block;
                int end_y = start_y + height_block;
                int num = i + block * j;
                //遍历小块,计算直方图
                for (int ii = start_x; ii < end_x; ii++)
                {
                    for (int jj = start_y; jj < end_y; jj++)
                    {
                        int index = img.at<uchar>(jj, ii);
                        //结果直接写入AHE_GO中去
                        CLAHE_GO.at<uchar>(jj, ii) = C2[num][index] * 255;
                    }
                }
            }
    
        }
        return CLAHE_GO;
    }
    
    Mat ImageClahe(Mat img, int block)
    {
        Mat CLAHE_GO = img.clone();
        //int block = _step;//pblock
        int width = img.cols;
        int height = img.rows;
        int width_block = width / block; //每个小格子的长和宽
        int height_block = height / block;
        //存储各个直方图
        int tmp2[8 * 8][256] = { 0 };
        float C2[8 * 8][256] = { 0.0 };
        //分块
        int total = width_block * height_block;
        for (int i = 0; i < block; i++)
        {
            for (int j = 0; j < block; j++)
            {
                int start_x = i * width_block;
                int end_x = start_x + width_block;
                int start_y = j * height_block;
                int end_y = start_y + height_block;
                int num = i + block * j;
                //遍历小块,计算直方图
                for (int ii = start_x; ii < end_x; ii++)
                {
                    for (int jj = start_y; jj < end_y; jj++)
                    {
                        int index = img.at<uchar>(jj, ii);
                        tmp2[num][index]++;
                    }
                }
                //裁剪和增加操作,也就是clahe中的cl部分
                //这里的参数 对应《Gem》上面 fCliplimit = 4 , uiNrBins = 255
                int average = width_block * height_block / 255;
                //关于参数如何选择,需要进行讨论。不同的结果进行讨论
                //关于全局的时候,这里的这个cl如何算,需要进行讨论
                int LIMIT = 40 * average;
                int steal = 0;
                for (int k = 0; k < 256; k++)
                {
                    if (tmp2[num][k] > LIMIT) {
                        steal += tmp2[num][k] - LIMIT;
                        tmp2[num][k] = LIMIT;
                    }
                }
                int bonus = steal / 256;
                //hand out the steals averagely
                for (int k = 0; k < 256; k++)
                {
                    tmp2[num][k] += bonus;
                }
                //计算累积分布直方图
                for (int k = 0; k < 256; k++)
                {
                    if (k == 0)
                        C2[num][k] = 1.0f * tmp2[num][k] / total;
                    else
                        C2[num][k] = C2[num][k - 1] + 1.0f * tmp2[num][k] / total;
                }
            }
        }
        //计算变换后的像素值
        //根据像素点的位置,选择不同的计算方法
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                //four coners
                if (i <= width_block / 2 && j <= height_block / 2)
                {
                    int num = 0;
                    CLAHE_GO.at<uchar>(j, i) = (int)(C2[num][CLAHE_GO.at<uchar>(j, i)] * 255);
                }
                else if (i <= width_block / 2 && j >= ((block - 1)*height_block + height_block / 2)) {
                    int num = block * (block - 1);
                    CLAHE_GO.at<uchar>(j, i) = (int)(C2[num][CLAHE_GO.at<uchar>(j, i)] * 255);
                }
                else if (i >= ((block - 1)*width_block + width_block / 2) && j <= height_block / 2) {
                    int num = block - 1;
                    CLAHE_GO.at<uchar>(j, i) = (int)(C2[num][CLAHE_GO.at<uchar>(j, i)] * 255);
                }
                else if (i >= ((block - 1)*width_block + width_block / 2) && j >= ((block - 1)*height_block + height_block / 2)) {
                    int num = block * block - 1;
                    CLAHE_GO.at<uchar>(j, i) = (int)(C2[num][CLAHE_GO.at<uchar>(j, i)] * 255);
                }
                //four edges except coners
                else if (i <= width_block / 2)
                {
                    //线性插值
                    int num_i = 0;
                    int num_j = (j - height_block / 2) / height_block;
                    int num1 = num_j * block + num_i;
                    int num2 = num1 + block;
                    float p = (j - (num_j*height_block + height_block / 2)) / (1.0f*height_block);
                    float q = 1 - p;
                    CLAHE_GO.at<uchar>(j, i) = (int)((q*C2[num1][CLAHE_GO.at<uchar>(j, i)] + p * C2[num2][CLAHE_GO.at<uchar>(j, i)]) * 255);
                }
                else if (i >= ((block - 1)*width_block + width_block / 2)) {
                    //线性插值
                    int num_i = block - 1;
                    int num_j = (j - height_block / 2) / height_block;
                    int num1 = num_j * block + num_i;
                    int num2 = num1 + block;
                    float p = (j - (num_j*height_block + height_block / 2)) / (1.0f*height_block);
                    float q = 1 - p;
                    CLAHE_GO.at<uchar>(j, i) = (int)((q*C2[num1][CLAHE_GO.at<uchar>(j, i)] + p * C2[num2][CLAHE_GO.at<uchar>(j, i)]) * 255);
                }
                else if (j <= height_block / 2) {
                    //线性插值
                    int num_i = (i - width_block / 2) / width_block;
                    int num_j = 0;
                    int num1 = num_j * block + num_i;
                    int num2 = num1 + 1;
                    float p = (i - (num_i*width_block + width_block / 2)) / (1.0f*width_block);
                    float q = 1 - p;
                    CLAHE_GO.at<uchar>(j, i) = (int)((q*C2[num1][CLAHE_GO.at<uchar>(j, i)] + p * C2[num2][CLAHE_GO.at<uchar>(j, i)]) * 255);
                }
                else if (j >= ((block - 1)*height_block + height_block / 2)) {
                    //线性插值
                    int num_i = (i - width_block / 2) / width_block;
                    int num_j = block - 1;
                    int num1 = num_j * block + num_i;
                    int num2 = num1 + 1;
                    float p = (i - (num_i*width_block + width_block / 2)) / (1.0f*width_block);
                    float q = 1 - p;
                    CLAHE_GO.at<uchar>(j, i) = (int)((q*C2[num1][CLAHE_GO.at<uchar>(j, i)] + p * C2[num2][CLAHE_GO.at<uchar>(j, i)]) * 255);
                }
                //双线性插值
                else {
                    int num_i = (i - width_block / 2) / width_block;
                    int num_j = (j - height_block / 2) / height_block;
                    int num1 = num_j * block + num_i;
                    int num2 = num1 + 1;
                    int num3 = num1 + block;
                    int num4 = num2 + block;
                    float u = (i - (num_i*width_block + width_block / 2)) / (1.0f*width_block);
                    float v = (j - (num_j*height_block + height_block / 2)) / (1.0f*height_block);
                    CLAHE_GO.at<uchar>(j, i) = (int)((u*v*C2[num4][CLAHE_GO.at<uchar>(j, i)] +
                        (1 - v)*(1 - u)*C2[num1][CLAHE_GO.at<uchar>(j, i)] +
                        u * (1 - v)*C2[num2][CLAHE_GO.at<uchar>(j, i)] +
                        v * (1 - u)*C2[num3][CLAHE_GO.at<uchar>(j, i)]) * 255);
                }
                //最后这步,类似高斯平滑
                CLAHE_GO.at<uchar>(j, i) = CLAHE_GO.at<uchar>(j, i) + (CLAHE_GO.at<uchar>(j, i) << 8) + (CLAHE_GO.at<uchar>(j, i) << 16);
            }
        }
        return CLAHE_GO;
    }
  • 相关阅读:
    大型网站架构系列——分布式消息队列
    docker 搭建lnmp环境以及docker常用命令
    编译PHP扩展amqp & php消息队列 rabbitmq
    python @staticmethod和@classmethod的作用
    Sqlalchemy model 文件自动生成
    正则表达式–零宽断言-赵兴壮
    php 编码规范
    MySQL8.0 InnoDB并行执行
    MySQL8.0 新特性 Hash Join
    MySQL8.0 redo日志系统优化
  • 原文地址:https://www.cnblogs.com/hsy1941/p/11918105.html
Copyright © 2011-2022 走看看