• 【OpenCV】图像增强---灰度变换、直方图均衡化


    图像增强的目的:改善图像的视觉效果或使图像更适合于人或机器的分析处理。通过图像增强,可以减少图像噪声,提高目标与背景的对比度,也可以增强或抑制图像中的某些细节。

     ---------------------------------------------------------------------------------------------------

    灰度变换:把原图像的像素灰度经过某个函数变换成新图像的灰度。可分为直线灰度变换法和直方图修正法。

    直线灰度变换法:线性、分段线性、非线性变换。

    直方图修正法:直方图均衡化、直方图规定化。

     ---------------------------------------------------------------------------------------------------

    图像直方图:是对像素的某种属性(如灰度、颜色、梯度等)分布进行统计分析的重要手段。

    灰度直方图:是灰度级的函数,它反映了图像中每一灰度级出现的次数或频率。

    直方图均衡化:把原始图像的直方图变换为均匀分布的形式,从而增加图像灰度的动态范围,以达到增强图像对比度的效果。

    经过均衡化处理的图像,其灰度级出现的概率相同,此时图像的熵最大,图像所包含的信息量最大。

    【注意,离散后是每块区域的概率相等,均衡化后并不是条直线哦。】

      细节概念等省略......

    ---------------------------------------------------------------------------------------------------

     线性灰度增强、对数变换、指数变换、直方图均衡化。代码见下(代码略粗糙...)【ImageEnhance.cpp部分代码】

      1 //线性灰度增强
      2 bool CImageEnhance::GrayLinearTransform(Mat &src, Mat &dst, uchar c, uchar d)  
      3 {  
      4     int b=0,a=255; 
      5     dst = src.clone();
      6     int row = dst.rows, col = dst.cols * dst.channels();
      7     uchar *cc = dst.data;
      8     for(int i = 0; i < row; ++i) {
      9         for(int j = 0; j < col; ++j) {
     10             int val = *cc;
     11             if(a > val) a = val;
     12             if(b < val) b = val;
     13             cc++;
     14         }
     15     }
     16     cc = dst.data;
     17     float k = float(d - c)/(b-a);  
     18     //CString c1; c1.Format(_T("a=%d,b=%d,c=%d,d=%d,k=%.2f
    "), a,b,c,d,k);MessageBox(c1); 
     19     for(int i = 0; i < row; ++i) {
     20         for(int j = 0; j < col; ++j) {
     21             int val = *cc;
     22             int s = (int)(k*(val - a) + c);
     23             *cc = s;
     24             cc++;
     25         }
     26     }
     27     return true;  
     28 }  
     29 //对数变换 
     30 bool CImageEnhance::GraynoLinearlog(Mat &src, Mat &dst)  { 
     31     dst = src.clone();
     32     int row = dst.rows, col = dst.cols * dst.channels();
     33     uchar *cc = dst.data;
     34     double k = 255 / log10(256.0); 
     35     for(int i = 0; i < row; ++i) {
     36         for(int j = 0; j < col; ++j) {
     37             int val = *cc;
     38             *cc = k * log10(1.0*(val + 1));
     39             cc++;
     40         }
     41     }
     42     return true;  
     43 }  
     44 //指数变换  
     45 bool CImageEnhance::GraynoLinearindex(Mat &src, Mat &dst)  {
     46     dst = src.clone();
     47     int row = dst.rows, col = dst.cols * dst.channels();
     48     uchar *cc = dst.data;
     49     double k = 1.0 / 255; 
     50     for(int i = 0; i < row; ++i) {
     51         for(int j = 0; j < col; ++j) {
     52             int val = *cc;
     53             *cc = k * val * val;    
     54             cc++;
     55         }
     56     }
     57     return true;  
     58 }  
     59 
     60 MatND CImageEnhance::getHist1(Mat& image)
     61 {
     62     MatND hist;
     63     int channels[] = {0};
     64     int dims = 1;
     65     int histSize[] = {256};   //直方图箱子的个数
     66     float granges[] = {0, 255};
     67     const float *ranges[] = {granges};  //像素值范围
     68     //计算直方图
     69     calcHist(&image, 1, channels, Mat()/*不使用掩码*/, hist, dims/*这是一维的直方图*/, histSize, ranges);  
     70     return hist;  //这里得到的hiat是256行一列的Mat
     71 }
     72 
     73 //直方图均衡化
     74 bool CImageEnhance::Equalize_hist(cv::Mat& src,cv::Mat& dst)
     75 {
     76     //CMFC_Test_lyyDlg pic;
     77     MatND hist;
     78     int channels[] = {0};
     79     int dims = 1;
     80     int histSize[] = {256};   //直方图箱子的个数
     81     float granges[] = {0, 255};
     82     const float *ranges[] = {granges};  //像素值范围
     83     //计算直方图
     84     Mat image = src.clone();
     85     calcHist(&image, 1, channels, Mat()/*不使用掩码*/, hist, dims/*这是一维的直方图*/, histSize, ranges);  
     86     
     87     //MatND hist = getHist1(src);//pic.getHist(dst);
     88     float s[256];
     89     float p[256];
     90 
     91     cv::Mat lookup(cv::Size(1, 256), CV_8U);
     92     int pixNum = src.cols * src.rows;//总像素个数
     93     for (int i =0; i <256; i++) {
     94         s[i] = hist.at<float>(i) / pixNum;
     95         if (i ==0) {
     96             p[i] = s[i];
     97         } 
     98         else {
     99             p[i] = p[i -1] + s[i];
    100         }
    101     }
    102     for (int i =0; i <256; i++) {
    103         lookup.at <uchar>(i) = static_cast<uchar>(p[i]*255.0);
    104     }
    105   
    106     cv::LUT(src, lookup, dst);//创建矩阵,把一个像素值映射到另一个像素值
    107     return true;
    108 }
    ImageEnhance.cpp

    效果如下:

    原图像:

    线性灰度增强:我这里默认a和b表示原图像灰度值的最小与最大值。以下示例取c=255,d=0,效果为使图像负像,即黑变白,白变黑。

      

    对数变换:(使图像的低灰度范围得以扩展而高灰度范围得以压缩,变换后的图像更符合人的视觉效果,因为人眼对高亮度的分辨率要求高于对低亮度的分辨率)

      

    指数变换:(指数大于1。与对数变换相反。)

     直方图均衡化:

    求原图像的灰度直方图代码:

     1 //获得直方图
     2 MatND getHistt(Mat& image){
     3     MatND hist;
     4     int channels[] = {0};
     5     int dims = 1;
     6     int histSize[] = {256};   //直方图箱子的个数
     7     float granges[] = {0, 255};
     8     const float *ranges[] = {granges};  //像素值范围
     9     //计算直方图
    10     calcHist(&image, 1, channels, Mat()/*不使用掩码*/, hist, dims/*这是一维的直方图*/, histSize, ranges);  
    11     return hist;  //这里得到的hiat是256行一列的Mat
    12 }
    13 //  将图像的直方图展示出来
    14 Mat draw_Hist(Mat &inputImage)
    15 {
    16     cv::MatND hist = getHistt(inputImage);
    17     Mat showImage(256, 256, CV_8U,Scalar(255));
    18     int i;
    19     double maxValue = 0;
    20     minMaxLoc(hist, 0, &maxValue, 0, 0);
    21     for(i = 0; i < 256; i++)
    22     {
    23         float value = hist.at<float>(i);
    24         int intensity = saturate_cast<int>(256 - 256 * (value/maxValue));
    25         rectangle(showImage, Point(i, 256 - 1), Point((i+1)-1, intensity), Scalar(0));
    26     }
    27     //namedWindow("gray"); imshow("gray", showImage);
    28     //cvMoveWindow("gray", 300, 300);
    29     //waitKey(0);
    30     return showImage;
    31 }
    View Code

     直方图显示:以下展示的 为以上的原图像以及直方图均衡化后的图像的  灰度直方图。

      

  • 相关阅读:
    [LeetCode] 769. Max Chunks To Make Sorted
    [LeetCode] 563. Binary Tree Tilt
    [LeetCode] 1802. Maximum Value at a Given Index in a Bounded Array
    [LeetCode] 1198. Find Smallest Common Element in All Rows
    [LeetCode] 370. Range Addition
    [LeetCode] 1749. Maximum Absolute Sum of Any Subarray
    [LeetCode] 1801. Number of Orders in the Backlog
    [LeetCode] 869. Reordered Power of 2
    [LeetCode] 841. Keys and Rooms
    [LeetCode] 1603. Design Parking System
  • 原文地址:https://www.cnblogs.com/GraceSkyer/p/8613042.html
Copyright © 2020-2023  润新知