實現直方圖均衡化(java+opencv)


什么是直方圖均衡化?

直方圖均衡化是一種簡單有效的圖像增強技術,通過改變圖像的直方圖來改變圖像中各像素的灰度,主要用於增強動態范圍偏小的圖像的對比度。原始圖像由於其灰度分布可能集中在較窄的區間,造成圖像不夠清晰。例如,過曝光圖像的灰度級集中在高亮度范圍內,而曝光不足將使圖像灰度級集中在低亮度范圍內。采用直方圖均衡化,可以把原始圖像的直方圖變換為均勻分布(均衡)的形式,這樣就增加了像素之間灰度值差別的動態范圍,從而達到增強圖像整體對比度的效果。換言之,直方圖均衡化的基本原理是:對在圖像中像素個數多的灰度值(即對畫面起主要作用的灰度值)進行展寬,而對像素個數少的灰度值(即對畫面不起主要作用的灰度值)進行歸並,從而增大對比度,使圖像清晰,達到增強的目的。舉個例子,如圖中所示,左圖為原始圖像,右圖為直方圖均衡化后的圖像。

個人的理解是,直方圖可以提高圖像的對比度,對於原本對比度較低的圖像效果比較明顯。

直方圖的概念

對一幅灰度圖像,其直方圖反映了該圖像中不同灰度級出現的統計情況。圖2給出了一個直方圖的示例,其中圖(a)是一幅圖像,其灰度直方圖可表示為圖(b),其中橫軸表示圖像的各灰度級,縱軸表示圖像中各灰度級像素的個數。(需要注意,灰度直方圖表示了在圖像中各個單獨灰度級的分布,而圖像對比度則取決於相鄰近像素之間灰度級的關系。)

嚴格地說,圖像的灰度直方圖是一個一維的離散函數,可寫成:

                                                                                        (公式1)

式中,是圖像中灰度級為的像素的個數。直方圖的每一列(稱為bin)的高度對應。直方圖提供了原圖中各種灰度值分布的情況,也可以說直方圖給出了一幅圖像所有灰度值的整體描述。直方圖的均值和方差也是圖像灰度的均值和方差。圖像的視覺效果與其直方圖有對應關系,或者說,直方圖的形狀和改變對圖像有很大的影響。

在直方圖的基礎上,進一步定義歸一化的直方圖為灰度級出現的相對頻率。即:

                                                                                                   (公式2)

式中,表示圖像的像素的總數,是圖像中灰度級為的像素的個數。

直方圖均衡化的步驟

 

 

 使用java實現直方圖均衡化

import java.util.LinkedList;
import java.util.List;

import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfFloat;
import org.opencv.core.MatOfInt;
import org.opencv.core.Scalar;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class huiduhua {


        //靜態代碼塊加載動態鏈接庫
        static {
            System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        }

        public static void main(String[] args) {

            /*
             * IMREAD_UNCHANGED = -1 :不進行轉化,比如保存為了16位的圖片,讀取出來仍然為16位。
             * IMREAD_GRAYSCALE = 0 :進行轉化為灰度圖,比如保存為了16位的圖片,讀取出來為8位,類型為CV_8UC1。
             * IMREAD_COLOR = 1 :進行轉化為三通道圖像。
             * IMREAD_ANYDEPTH = 2 :如果圖像深度為16位則讀出為16位,32位則讀出為32位,其余的轉化為8位。
             * IMREAD_ANYCOLOR = 4 :圖像以任何可能的顏色格式讀取
             * IMREAD_LOAD_GDAL = 8 :使用GDAL驅動讀取文件,GDAL(Geospatial Data Abstraction
             * Library)是一個在X/MIT許可協議下的開源柵格空間數據轉換庫。它利用抽象數據模型來表達所支持的各種文件格式。
             *    它還有一系列命令行工具來進行數據轉換和處理。
             */

            Mat src = Imgcodecs.imread("./data/huiduhua.png",0);
            //Imgproc.resize(src, src, new Size(src.cols()/2,src.rows()/2));

            HighGui.imshow("原圖", src);
            HighGui.waitKey();

            ImgCalcHist(src,"原圖直方圖");

            Mat dst = new Mat();
            //直方圖均衡化,該算法對亮度進行歸一化並增加圖像的對比度。
            Imgproc.equalizeHist(src,dst);
            HighGui.imshow("直方圖均衡化", dst);
            HighGui.waitKey();

            ImgCalcHist(dst,"直方圖均衡化后的直方圖");

        }

        /**
         * 直方圖
         * @param src
         * @param windowName
         */
        public static void ImgCalcHist(Mat src,String windowName) {

            List<Mat> matList = new LinkedList<Mat>();
            matList.add(src);

            Mat histogram = new Mat();

            MatOfFloat ranges=new MatOfFloat(0,256);
            MatOfInt histSize = new MatOfInt(300);

            /*
             * 計算直方圖
             * List<Mat> images:輸入圖像
             * MatOfInt channels:需要統計直方圖的第幾通道
             * Mat mask:掩膜,,計算掩膜內的直方圖
             * Mat hist:輸出的直方圖數組
             * MatOfInt histSize:指的是直方圖分成多少個區間,就是bin的個數
             * MatOfFloat ranges: 統計像素值得區間
             */
            Imgproc.calcHist(matList,new MatOfInt(0),new Mat(),histogram,histSize ,ranges);
            //創建直方圖面板
            Mat histImage = Mat.zeros( 150, (int)histSize.get(0, 0)[0], CvType.CV_8UC1);
            //歸一化直方圖 詳見https://blog.csdn.net/ren365880/article/details/103923813
            Core.normalize(histogram, histogram, 1, histImage.rows() , Core.NORM_MINMAX, -1, new Mat() );
            //繪制直線 詳見:https://blog.csdn.net/ren365880/article/details/103952856
            for( int i = 0; i < (int)histSize.get(0, 0)[0]; i++ ){
                Imgproc.line(histImage,new org.opencv.core.Point(i, histImage.rows()),new org.opencv.core.Point(i, histImage.rows()-Math.round( histogram.get(i,0)[0])) ,new Scalar( 255, 255, 255),1, 8, 0 );
            }
            HighGui.imshow(windowName, histImage);
            HighGui.waitKey();
        }


    }

效果:

 

 

 

 

 

 

參考資料:https://blog.csdn.net/qq_15971883/article/details/88699218

https://blog.csdn.net/zaibeijixing/article/details/96336864

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM