Go Convertir une image couleur en niveaux de gris


Exemple

Certains algorithmes de traitement d'images numériques, tels que la détection des contours, les informations portées par l'intensité de l'image (valeur d'échelle de gris) sont suffisants. L'utilisation des informations de couleur (canal R, G, B ) peut fournir un résultat légèrement meilleur, mais la complexité de l'algorithme sera accrue. Ainsi, dans ce cas, nous devons convertir l'image couleur en image en niveaux de gris avant d'appliquer un tel algorithme.

Le code suivant est un exemple de conversion d'image arbitraire en image en niveaux de gris de 8 bits. L'image est extraite de l'emplacement distant en utilisant net/http package net/http , convertie en niveaux de gris et finalement enregistrée en tant qu'image PNG.

package main

import (
    "image"
    "log"
    "net/http"
    "os"

    _ "image/jpeg"
    "image/png"
)

func main() {
    // Load image from remote through http
    // The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/)
    // Images are available under the Creative Commons 3.0 Attributions license.
    resp, err := http.Get("http://golang.org/doc/gopher/fiveyears.jpg")
    if err != nil {
        // handle error
        log.Fatal(err)
    }
    defer resp.Body.Close()

    // Decode image to JPEG
    img, _, err := image.Decode(resp.Body)
    if err != nil {
        // handle error
        log.Fatal(err)
    }
    log.Printf("Image type: %T", img)

    // Converting image to grayscale
    grayImg := image.NewGray(img.Bounds())
    for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
        for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
            grayImg.Set(x, y, img.At(x, y))
        }
    }

    // Working with grayscale image, e.g. convert to png
    f, err := os.Create("fiveyears_gray.png")
    if err != nil {
        // handle error
        log.Fatal(err)
    }
    defer f.Close()

    if err := png.Encode(f, grayImg); err != nil {
        log.Fatal(err)
    }
}

La conversion de couleur se produit lors de l’attribution de pixels via Set(x, y int, c color.Color) implémentée dans image.go as

func (p *Gray) Set(x, y int, c color.Color) {
    if !(Point{x, y}.In(p.Rect)) {
        return
    }

    i := p.PixOffset(x, y)
    p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
}

dans lequel color.GrayModel est défini dans color.go comme

func grayModel(c Color) Color {
    if _, ok := c.(Gray); ok {
        return c
    }
    r, g, b, _ := c.RGBA()

    // These coefficients (the fractions 0.299, 0.587 and 0.114) are the same
    // as those given by the JFIF specification and used by func RGBToYCbCr in
    // ycbcr.go.
    //
    // Note that 19595 + 38470 + 7471 equals 65536.
    //
    // The 24 is 16 + 8. The 16 is the same as used in RGBToYCbCr. The 8 is
    // because the return value is 8 bit color, not 16 bit color.
    y := (19595*r + 38470*g + 7471*b + 1<<15) >> 24

    return Gray{uint8(y)}
}

Sur la base des faits ci-dessus, l'intensité Y est calculée avec la formule suivante:

Luminance: Y = 0,299 R + 0,587 G + 0,114 B

Si nous voulons appliquer différentes formules / algorithmes pour convertir une couleur en une intésité, par exemple

Moyenne: Y = ( R + G + B ) / 3
Luma: Y = 0,2126 R + 0,7152 G + 0,0722 B
Lustre: Y = (min ( R , G , B ) + max ( R , G , B )) / 2

Ensuite, les extraits suivants peuvent être utilisés.

// Converting image to grayscale
grayImg := image.NewGray(img.Bounds())
for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
    for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
        R, G, B, _ := img.At(x, y).RGBA()
        //Luma: Y = 0.2126*R + 0.7152*G + 0.0722*B
        Y := (0.2126*float64(R) + 0.7152*float64(G) + 0.0722*float64(B)) * (255.0 / 65535)
        grayPix := color.Gray{uint8(Y)}
        grayImg.Set(x, y, grayPix)
    }
}

Le calcul ci-dessus est effectué par multiplication en virgule flottante, et n'est certainement pas le plus efficace, mais il suffit pour démontrer l'idée. L'autre point est, lorsque vous appelez Set(x, y int, c color.Color) avec color.Gray comme troisième argument, le modèle de couleur n'effectuera pas la conversion de couleur comme on peut le voir dans la fonction grayModel précédente.