F #, augmentant le contraste de l'image en alignant les histogrammes

L'opération d' alignement de l'histogramme (augmentation du contraste) est souvent utilisée pour augmenter la qualité de l'image. Dans le cadre de cet article, le concept d' histogramme , la théorie d'un algorithme pour son alignement, et des exemples pratiques de fonctionnement de cet algorithme seront considérés . Pour faciliter le traitement des images, nous utiliserons la bibliothÚque OpenCV . Nous ferons également une analyse comparative des résultats de notre algorithme et de l'algorithme déjà intégré à OpenCV .



L'histogramme est une fonction h (x) , qui renvoie le nombre total de pixels dont la luminosité est égale à x .


L'histogramme h de l' image demi - teinte I est donné par

h(m)=|(r,c)|je(r,c)=m|


, m

.


//   H    I.

procedure histogram(I,H);
{
    //     .
    for i := 0 to MaxVal
        H[i] := 0;

    //   .
    for L := 0 to MaxRow
        for P := 0 to MaxCol {
            grayval := I[r,c];
            H[grayval] := H[grayval] + 1;
        };
}

, . 0 255, 256. , .


, — 256 ( ), . .


1. h(x)



. — cdf(x) .


, OpenCV , , . , , . F# OpenCVSharp4.


, Visual Studio, . , MacOS, , "runtimes/osx-x64/native/libOpenCvSharpExtern.dylib" , .
Unable to load shared library 'OpenCvSharpExtern' or one of its dependencies


,


open OpenCvSharp
open Microsoft.FSharp.NativeInterop

// mat -   Mat  OpenCV
let getHistogram (mat: Mat) =
    //   
    let hx = Array.zeroCreate<int> 256
    //  
    mat.ForEachAsByte(fun value _ ->
                           let v = int (NativePtr.get value 0)
                           hx.[v] <- hx.[v] + 1)
    //  
    hx

, . X


créX(X)=h(0)+h(1)+...+h(X)


, X. 1 ( ).


, cdf(x)


let getCdx hx = // hx - 
   //   
   hx |> Array.mapi (fun x _ -> if x > 0 then hx.[0..(x-1)] |> Array.sum else 0)


1 , . ( ), . , , .


2.


2.



, .


:


F(X)=rounrĂ©(crĂ©F(X)-crĂ©FmjenpjeXels-1⋅255)



cdf(x) — X
cdf_min — ,
pixels —
255 — . 255
round —


F# :


//  cdf_min
let cdxMin = cdx |> Array.filter (fun v -> v > 0) |> Array.min
//      
let totalPixels = src.Rows * src.Cols // src -   Mat   

for y in 0..src.Rows do
    for x in 0..src.Cols do
        //     
        let s = int(src.At<byte>(y, x))
        //     
        let fx = (float(cdx.[s]) - float(cdxMin))/(float(totalPixels - 1))*255.
        //    
        equalizeImage.Circle(x, y, 1, new Scalar(double(fx)))

, . . , OpenCV .


// Learn more about F# at http://fsharp.org
open OpenCvSharp
open Microsoft.FSharp.NativeInterop

//     
let getHistogram (mat: Mat) =
    let hx = Array.zeroCreate<int> 256
    mat.ForEachAsByte(fun value _ ->
                           let v = int (NativePtr.get value 0)
                           hx.[v] <- hx.[v] + 1)
    hx

//      
let getCdx hx =
    hx |> Array.mapi (fun x _ -> if x > 0 then hx.[0..(x-1)] |> Array.sum else 0)

//     
let drawHistogramAndCdx hx cdx (mat: Mat) =
    let histoWidth = 256
    let histoHeight = 256

    //     
    let cdxMax = cdx |> Array.max
    //      ( )
    //    
    let cdxK = float(histoHeight)/float(cdxMax)

    let histMax = hx |> Array.max
    let histK = float(histoHeight)/float(histMax)

    let histMat = new Mat(histoWidth, histoHeight, MatType.CV_8UC4)
    hx
    |> Array.iteri (fun x v ->
                        let histDy = int(float(v)*histK)
                        let cdxDy = int(float(cdx.[x])*cdxK)
                        //   h(x)
                        mat.Line(x, histoHeight-1, x, histoHeight-1-histDy, Scalar.White)
                        //    cdx(x)
                        mat.Circle(x, histoHeight-cdxDy, 1, Scalar.Blue))

[<EntryPoint>]
let main argv =

    let histoWidth = 256
    let histoHeight = 256

    let src = Cv2.ImRead("cat.jpg", ImreadModes.Grayscale)
    let equalizeImage = new Mat(src.Rows, src.Cols, MatType.CV_8UC1)

    // calculate histogram h(x)
    let hx = getHistogram src

    // calculate cdf(x) = h(0) + h(1) + .. + h(x)
    let cdx = getCdx hx

    // draw histogram
    let histMat = new Mat(histoWidth, histoHeight, MatType.CV_8UC4)
    drawHistogramAndCdx hx cdx histMat

    // equalize the histogram
    let cdxMin = cdx |> Array.filter (fun v -> v > 0) |> Array.min
    let totalPixels = src.Rows * src.Cols

    for y in 0..src.Rows do
        for x in 0..src.Cols do
            let s = int(src.At<byte>(y, x))
            let fx = (float(cdx.[s]) - float(cdxMin))/(float(totalPixels - 1))*255.
            //equalizeImage.Set<Scalar>(y, x, new Scalar(double(fx)))
            equalizeImage.Circle(x, y, 1, new Scalar(double(fx)))

    // calculate equalize histogram
    let hx2 = getHistogram equalizeImage
    let cdx2 = getCdx hx2

    let histMat2 = new Mat(histoWidth, histoHeight, MatType.CV_8UC4)
    drawHistogramAndCdx hx2 cdx2 histMat2

    // opencv equalize histogram
    let opencCVImage = new Mat(src.Rows, src.Cols, MatType.CV_8UC1)
    let in1 = InputArray.Create(src)
    let in2 = OutputArray.Create(opencCVImage)

    Cv2.EqualizeHist(in1, in2)

    // get opencv histogram
    let hx3 = getHistogram opencCVImage
    let cdx3 = getCdx hx3

    let histMat3 = new Mat(histoWidth, histoHeight, MatType.CV_8UC4)
    drawHistogramAndCdx hx3 cdx2 histMat3

    // show results
    use w1 = new Window("original image", src)
    use w2 = new Window("original histogram", histMat)

    use w3 = new Window("custom equalize image", equalizeImage)
    use w4 = new Window("custom equalize histogram", histMat2)

    use w5 = new Window("opencv equalize image", opencCVImage)
    use w6 = new Window("opencv equalize histogram", histMat3)

    Cv2.WaitKey() |> ignore

    0 // return an integer exit code


3.


, , OpenCV.


( ), — , — OpenCV.







L'auteur de l'article est loin d'ĂȘtre original et n'a rien trouvĂ© de nouveau, prĂ©sentant au public une autre histoire sur la façon dont l'algorithme d'alignement d'histogramme est mis en Ɠuvre et pourquoi il est nĂ©cessaire. Le but principal de l'article n'Ă©tait pas seulement de parler de l'algorithme, mais aussi de donner des exemples pratiques spĂ©cifiques et des codes sources que vous pouvez copier et vĂ©rifier vous-mĂȘme, et Ă©ventuellement expĂ©rimenter. Bien sĂ»r, l'algorithme d'histogramme n'est pas le seul utilisĂ© pour filtrer les images. Mais c'est le sujet d'autres questions.


All Articles