quinta-feira, 9 de novembro de 2017

Convertendo Imagens para Preto e Branco

Aqui vamos tirar proveito da habilidade do Powershell em obter as informações de um arquivo de imagem pixel a pixel. Powershell é capaz de obter os atributos ARGB do pixel. Com isso, podemos implementar algoritmos para criar uma imagem em preto e branco, ou melhor dizendo, em tons de cinza, a partir de um arquivo de imagem colorida fornecido.

Implementaremos 3 algoritmos básicos:
  • AVERAGE
  • ## METODO AVERAGE
    ## Compõe cada novo RGB em escala de cinza
    ## Somando-se RGB colorido e dividindo por 3
    $R = (($ColorPixel.R)+($ColorPixel.G)+($ColorPixel.B)) / 3
    $G = (($ColorPixel.R)+($ColorPixel.G)+($ColorPixel.B)) / 3
    $B = (($ColorPixel.R)+($ColorPixel.G)+($ColorPixel.B)) / 3
    

  • LIGHTNESS
  • ## METODO LIGHTNESS
    ## Compõe cada novo RGB em escala de cinza
    ## Calculando: (Max(RGB)+Min(RGB)) / 2
    $R = ((MaxRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B)) + `
                         (MinRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B))) / 2
    $G = ((MaxRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B)) + `
                         (MinRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B))) / 2
    $B = ((MaxRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B)) + `
                         (MinRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B))) / 2
    

  • LUMINOSITY
  • ## METODO LUMINOSITY
    ## Calcula cada novo RGB em escala de cinza
    ## Através de pesos diferentes em cada RGB
    ## R tem peso 0.2155
    ## G tem pseo 0.7154
    ## B tem peso 0.0721
    $R = (0.2125*$ColorPixel.R)+(0.7154*$ColorPixel.G)+(0.0721*$ColorPixel.B)
    $G = (0.2125*$ColorPixel.R)+(0.7154*$ColorPixel.G)+(0.0721*$ColorPixel.B)
    $B = (0.2125*$ColorPixel.R)+(0.7154*$ColorPixel.G)+(0.0721*$ColorPixel.B)
    

O Script completo ficou assim:
Function PretoBranco([System.Drawing.Image]$Img, [String]$Metodo) {
    If ( ($Metodo.ToUpper() -eq "LUMINOSITY") -Or `
        ($Metodo.ToUpper() -eq "AVERAGE") -Or `
        ($Metodo.ToUpper() -eq "LIGHTNESS") ) {
        Write-Host -ForegroundColor Green "Convertendo a imagem para preto e branco..."
        Write-Host -ForegroundColor Green "Será salvo na mesma pasta um arquivo NomeOriginal_PretoBranco"
    }
    Else { 
        Write-Host -ForegroundColor Yellow "$Metodo [Método de conversão especificado não é suportado]"
        Write-Host -ForegroundColor White "Será utilizado o método: [LUMINOSITY]"
        $Metodo = "LUMINOSITY"
        Write-Host -ForegroundColor Green "Convertendo a imagem para preto e branco..."
        Write-Host -ForegroundColor Green "Será salvo na mesma pasta um arquivo NomeOriginal_PretoBranco"
    }
    [Int32]$p=0
    Foreach($y in (1..($Img.Height-1))) {
        $p++
        If ($p -gt (($Img.Height)*0.05)) { 
            Write-Host -NoNewLine '.'
            $p = 0
        }
        Foreach($x in (1..($Img.Width-1))) {
            $ColorPixel = $Img.GetPixel($x,$y)
            ## METODO LUMINOSITY
            If ($Metodo.ToUpper() -eq "LUMINOSITY") {
               $R = (0.2125*$ColorPixel.R)+(0.7154*$ColorPixel.G)+(0.0721*$ColorPixel.B)
               $G = (0.2125*$ColorPixel.R)+(0.7154*$ColorPixel.G)+(0.0721*$ColorPixel.B)
               $B = (0.2125*$ColorPixel.R)+(0.7154*$ColorPixel.G)+(0.0721*$ColorPixel.B)
            }

            ## METODO AVERAGE
            If ($Metodo.ToUpper() -eq "AVERAGE") {
                $R = (($ColorPixel.R)+($ColorPixel.G)+($ColorPixel.B)) / 3
                $G = (($ColorPixel.R)+($ColorPixel.G)+($ColorPixel.B)) / 3
                $B = (($ColorPixel.R)+($ColorPixel.G)+($ColorPixel.B)) / 3
            }

            ## METODO LIGHTNESS
            If ($Metodo.ToUpper() -eq "LIGHTNESS") {
                $R = ((MaxRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B)) + `
                     (MinRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B))) / 2
                $G = ((MaxRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B)) + `
                     (MinRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B))) / 2
                $B = ((MaxRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B)) + `
                     (MinRGB ($ColorPixel.R) ($ColorPixel.G) ($ColorPixel.B))) / 2
            }

            ## Set GrayScale Pixel
            $A = $ColorPixel.A
            $Img.SetPixel($x,$y,[System.Drawing.Color]::FromArgb([Int32]$A,[Int32]$R,[Int32]$G,[Int32]$B))
        } ## ForEach $x
    } ## ForEach $y
} ## EndFunction PretoBranco

Function MaxRGB([Int32]$R, [Int32]$G, [Int32]$B) {
    Return ([math]::Max([math]::Max($R,$G),$B))
}

Function MinRGB([Int32]$R, [Int32]$G, [Int32]$B) {
    Return ([math]::Min([math]::Min($R,$G),$B))
}

$Arquivo = New-Object System.Windows.Forms.OpenFileDialog
$Arquivo.filter = "Imagens (*.PNG;*.BMP;*.JPG;*.GIF)|*.PNG;*.BMP;*.JPG;*.GIF"
$Arquivo.ShowDialog() | Out-Null
$Ext = ($Arquivo.filename).Substring(($Arquivo.filename).Length-3,3)
$ArquivoSemExt = ($Arquivo.filename).Substring(0,($Arquivo.filename).Length-4)
$Img = [System.Drawing.Image]::FromFile($Arquivo.filename)

Clear-Host
Write-Host "##############################################"
Write-Host "Arquivo de Imagem:"$Arquivo.filename
Write-Host "##############################################"

PretoBranco $Img LUMINOSITY

Write-Host ""
Write-Host -ForegroundColor Yellow "Conversão concluída!"
$Img.Save($ArquivoSemExt+"_PretoBranco."+$Ext)
$Img.Dispose()

Abaixo, ilustra-se exemplos de execução com cada método. Observou-se baixo desempenho com o método LIGHTNESS, em decorrência das várias chamadas de função para os cálculos MaxRGB e MinRGB.

IMAGEM COLORIDA 1


MÉTODO LUMINOSITY


MÉTODO AVERAGE


MÉTODO LIGHTNESS


IMAGEM COLORIDA 2


MÉTODO LUMINOSITY


MÉTODO AVERAGE


MÉTODO LIGHTNESS

Nenhum comentário:

Postar um comentário