2013-07-12 27 views
7

Próbuję napisać algorytm konwerterów, który pobiera obraz JPEG i zwraca jego wersję PGM (Portable Gray Map). Problem polega na tym, że nie rozumiem, jak działają "oficjalne" konwertery JPG-> PGM pod względem wartości przypisanej do końcowego piksela (chyba 0-> 255), począwszy od klasycznego formatu RGB."Standardowa" konwertacja RGB na skalę szarości

Na początku, stosuje się ten wzór (to samo stosuje się w konwersji CV_RGB2GRAY OpenCV'S):

0,30 * R + 0,59 * G + 0,11 * B = Val

napisałem prosty kod przetestuj moje wyniki: pobiera obraz kolorowy i jego wersję PGM (już za pomocą GIMP). Następnie konwertuje obraz kolorowy przy użyciu poprzedniej formuły. Celem jest uzyskanie obrazu w skali szarości, który jest piksel-do-piksela równy wejściowi PGM.

W tym momencie nie zwraca tych samych wartości. Możesz mi pomóc?

+0

Czy już widziałeś [wikipedia: Skala szarości] (https://en.wikipedia.org/wiki/Grayscale)? – MrSmith42

+0

Czy jesteś pewien, że tak właśnie jest? Co jeśli to tylko dekoduje płaszczyznę Y i ignoruje współczynniki koloru? Miałbyś inny hałas, a czynniki mogą być inne. – harold

+0

Niestety, nie rozumiem Twojego wpisu – TheUnexpected

Odpowiedz

5

Problem polega na tym, że nie mogę zrozumieć, jak „oficjalny” jpg> convertitors PGM pracować w warunkach, jaką wartość przypisać do ostatecznego piksela (myślę, 0-> 255), począwszy od klasycznej Format RGB.

Prawdopodobnie korekta gamma występuje w konwersji wykorzystywanej przez "oficjalne" narzędzia.
To znaczy, to nie jest tylko transformacja liniowa.

Zobacz tę sekcję Wikipedii szczegółach: Converting color to grayscale

wierzę chcesz użyć formuły Csrgb.
Wypróbuj i sprawdź, czy odpowiada oczekiwanym wynikom.

Zasadniczo, można to zrobić:

  1. Take R, G, B kolor (każdy w [0,1] zasięgu)
    • Jeśli są w zakresie 0..255 Zamiast po prostu podzielić przez 255.0
  2. Compute Clinear = 0.2126 R + 0.7152 G + 0.0722 B
    • Jest to prawdopodobnie liniowy przekształcić zostałeś stosowania przed
  3. Compute Csrgb według jego formuła, oparta na Clinear
    • To kawałek nieliniowa korekcja gamma Ci brakowało
    • odjazdu this WolframAlpha plot
    • Csrgb = 12.92 Clinear gdy Clinear <= 0.0031308
    • Csrgb = 1.055 Clinear1/2.4 - 0.055 gdy Clinear > 0.0031308
+0

@ alessandro.francesconi Uaktualniłem odpowiedź, aby dokładnie opisać dokładne kroki, ponieważ strona Wikipedii może być trochę zagadkowa, jeśli nie znasz podstawowych informacji o kolorach. –

+1

@ alessandro.francesconi Dodałem także dla ciebie działkę WolframAlpha, abyś mógł zobaczyć nieliniowy kształt korekcji gamma. –

+0

Tymoteusz, proszę poprawić mnie, jeśli się mylę, ale myślę, że po kroku (1) trzeba przekształcić wartości na liniową intensywność, ponieważ kiedy przyjmuje się wartości RGB z pliku, są one już zakodowane za pomocą mocy gamma 1/2.4. Najpierw musisz usunąć to kodowanie, stosując transformację z mocą 2.4, a dopiero potem wykonaj kroki (2) i (3) swojej odpowiedzi. Czy to prawda? –

1

Teoretycznie z kilkoma pikselami (w tym przypadku 3) można określić, co robi algorytm. Juste odebrać swoje trzy pikseli (P1, P2, P3), ich wartości RGB i ich PGM wartość szarości i masz:

RedConstant * p1.redValue + GreenConstant * p1.greenValue + BlueConstant * p1.blueValue = p1 .grayValue

RedConstant * p2.redValue + GreenConstant * p2.greenValue + BlueConstant * p2.blueValue = p2.grayValue

RedConstant * p3.redValue + GreenConstant * p3.greenValue + BlueConstant * p3.blueValue = p3 .grayValue.

Następnie rozwiąż ten problem (poszukaj "rozwiązywania równań" lub czegoś podobnego) i zobacz jakie są stałe, których używają.

+0

Dzięki, ale nie, to nie działa. Umieściłem 3 wartości pikseli i rozwiązałem układ trzech równań. Powoduje to trzy stałe, które są dobre dla tych równań, a nie dla czwartego piksela. – TheUnexpected

+0

1) Czy jesteś pewien, że wybrałeś te same piksele dla wartości RGB i szarości? 2) z tego artykułu: http: //www.tannerhelland.com/3643/grayscale-image-algorithm-vb6/Widziałem, że było kilka różnych algorytmów RGB-to-PGM. Wypróbuj je wszystkie i spróbuj sprawdzić, który z nich jest używany. Powodzenia! – Fabinout

+0

Co, jeśli powiem, że nie znalazłem żadnej ważnej metody? – TheUnexpected

1

SIMPLE algorytm CONVERT Obraz RGB do skali szarości IN OpenCV PYTHON!

Użyłem komentarzy, więc kod jest niezrozumiały. Ale działa szybko.

import cv2 
import numpy as np 
img1 = cv2.imread('opencvlogo.png') 
row,col,ch = img1.shape 
g = [ ] #the list in which we will stuff single grayscale pixel value inplace of 3 RBG values 
#this function converts each RGB pixel value into single Grayscale pixel value and appends that value to list 'g' 
def rgb2gray(Img): 
    global g 
    row,col,CHANNEL = Img.shape 
    for i in range(row) : 
     for j in range(col): 
     a =  ( Img[i,j,0]*0.07 + Img[i,j,1]*0.72 + Img[i,j,2] *0.21 ) #the algorithm i used id , G = B*0.07 + G*0.72 + R* 0.21 
                        #I found it online 
     g.append(a) 
rgb2gray(img1) #convert the img1 into grayscale 
gr = np.array(g) #convert the list 'g' containing grayscale pixel values into numpy array 
cv2.imwrite("test1.png" , gr.reshape(row,col)) #save the image file as test1.jpg 

więc użyłem tego pliku obrazu ... enter image description here

Mój program wygenerowany następujący skali szarości pliku ..

enter image description here

0

Do punktu Harolda o "Y": standardowy kolor Pliki JPEG są kodowane przy użyciu przestrzeni kolorów YCbCr, gdzie Y jest składnikiem luminancji (tj. Jasnością), a Cb i Cr są składnikami chrominancji niebieskiej różnicy i czerwieni różnicy. Jednym ze sposobów obracania kolorowego JPEG w skali szarości jest po prostu upuszczenie komponentów Cb i Cr.

Istnieje narzędzie o nazwie jpegtran niż można to zrobić bezstratnie, używając opcji -grayscale. (Bezstratna część byłaby naprawdę ważna tylko wtedy, gdybyś chciał uzyskać plik JPEG, a nie PGM, aby uniknąć generation loss.) W każdym razie prawdopodobnie byłby to najszybszy sposób na przeprowadzenie tej transformacji, ponieważ nie dekoduje nawet obraz w piksele, a tym bardziej matematyka na każdym z nich.