web-dev-qa-db-fra.com

Comment puis-je augmenter le contraste d'une image dans Python OpenCV

Je suis nouveau sur Python OpenCV. J'ai lu certains documents et réponses ici mais je ne peux pas comprendre ce que signifie le code suivant:

if (self.array_alpha is None):
    self.array_alpha = np.array([1.25])
    self.array_beta = np.array([-100.0])

# add a beta value to every pixel 
cv2.add(new_img, self.array_beta, new_img)                    

# multiply every pixel value by alpha
cv2.multiply(new_img, self.array_alpha, new_img)  

J'ai appris que Basically, every pixel can be transformed as X = aY + b where a and b are scalars.. Fondamentalement, j'ai compris cela. Cependant, je n'ai pas compris le code et comment augmenter le contraste avec cela.

Jusqu'à présent, j'ai réussi à lire simplement l'image en utilisant img = cv2.imread('image.jpg',0)

Merci de votre aide

18
tsaebeht

Je voudrais suggérer une méthode utilisant le canal de couleur LAB. Wikipédia a suffisamment d'informations sur ce qu'est le canal de couleur LAB.

J'ai fait ce qui suit en utilisant OpenCV 3.0.0 et python:

import cv2

#-----Reading the image-----------------------------------------------------
img = cv2.imread('Dog.jpg', 1)
cv2.imshow("img",img) 

#-----Converting image to LAB Color model----------------------------------- 
lab= cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
cv2.imshow("lab",lab)

#-----Splitting the LAB image to different channels-------------------------
l, a, b = cv2.split(lab)
cv2.imshow('l_channel', l)
cv2.imshow('a_channel', a)
cv2.imshow('b_channel', b)

#-----Applying CLAHE to L-channel-------------------------------------------
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
cl = clahe.apply(l)
cv2.imshow('CLAHE output', cl)

#-----Merge the CLAHE enhanced L-channel with the a and b channel-----------
limg = cv2.merge((cl,a,b))
cv2.imshow('limg', limg)

#-----Converting image from LAB Color model to RGB model--------------------
final = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)
cv2.imshow('final', final)

#_____END_____#

Vous pouvez exécuter le code tel quel. Pour savoir de quoi parle CLAHE (Contrast Limited Adaptive Histogram Equalization), vous pouvez à nouveau consulter Wikipedia.

36
Jeru Luke

\\ ce message a été fortement modifié par rapport à l'original. le noyau de la réponse d'origine est conservé dans la note ci-dessous \\

Pour Python, je n'ai pas trouvé de fonction OpenCV qui offre un contraste. Comme d'autres l'ont suggéré, il existe certaines techniques pour augmenter automatiquement le contraste.

Dans les documents officiels OpenCV , il est suggéré que cette équation puisse être utilisée pour appliquer à la fois le contraste et la luminosité:

new_img = alpha * old_img + beta

où alpha correspond à un contraste et beta est la luminosité. Différents cas

alpha 1  beta 0      --> no change  
0 < alpha < 1        --> lower contrast  
alpha > 1            --> higher contrast  
-127 < beta < +127   --> good range for brightness values

En C/C++, vous pouvez implémenter cette équation en utilisant cv :: Mat :: convertTo, mais nous n'avons pas accès à cette partie de la bibliothèque à partir de Python. Pour le faire en Python, je recommanderais d'utiliser la fonction cv :: addWeighted , car elle est rapide et force automatiquement la sortie à être comprise entre 0 et 255 (par exemple pour une image couleur 24 bits , 8 bits par canal).

import cv2
img = cv2.imread('input.png')
# call addWeighted function. use beta = 0 to effectively only operate one one image
out = cv2.addWeighted( img, contrast, img, 0, brightness)
output = cv2.addWeighted

>>>>> Commencez la note <<<<<

Tel que publié à l'origine, j'ai fait référence à cette formule de ce livre GIMP en ligne] ( http://pippin.gimp.org/image_processing/chap_point.html ) is

new_image = (old_image - 0,5) × contraste + 0,5

et cette formule modifiée pour changer l'échelle de contraste pour passer de -127 à +127:

new_image = (old_image) × (contraste/127 + 1) - contraste

Ces formules donneront à la fois des changements de luminosité et de contraste, mais elles ont les points faibles:

  1. la deuxième formule n'est pas rigoureusement dérivée de la première
  2. ils ne correspondent pas aux comportements de luminosité et de contraste observés dans d'autres programmes (par exemple PhotoShop, GIMP, etc.)

>>>>> Note de fin <<<<<

À partir de maintenant, je vais essayer de reproduire le comportement généralement observé dans les programmes de retouche photo et en particulier le comportement dans GIMP.

Contraste

Dans le GIMP, les niveaux de contraste vont de -127 à +127. J'ai adapté les formules d'ici pour tenir dans cette plage.

f = 131 * (contraste + 127)/(127 * (131-contraste))
new_image = f * (old_image - 127) + 127 = f * (old_image) + 127 * (1-f)

Pour comprendre la luminosité, j'ai compris la relation entre la luminosité et les niveaux et utilisé les informations dans ce niveau post pour arriver à une solution.

#pseudo code
if brightness > 0
    shadow = brightness
    highlight = 255
else:
    shadow = 0
    highlight = 255 + brightness
new_img = ((highlight - shadow)/255)*old_img + shadow

luminosité et contraste en Python et OpenCV

Mettre tout cela ensemble et ajouter en utilisant l'image de référence "mandrill" de SC SIPI :

import cv2
import numpy as np

# Open a typical 24 bit color image. For this kind of image there are
# 8 bits (0 to 255) per color channel
img = cv2.imread('mandrill.png')  # mandrill reference image from USC SIPI

s = 128
img = cv2.resize(img, (s,s), 0, 0, cv2.INTER_AREA)

def apply_brightness_contrast(input_img, brightness = 0, contrast = 0):

    if brightness != 0:
        if brightness > 0:
            shadow = brightness
            highlight = 255
        else:
            shadow = 0
            highlight = 255 + brightness
        alpha_b = (highlight - shadow)/255
        gamma_b = shadow

        buf = cv2.addWeighted(input_img, alpha_b, input_img, 0, gamma_b)
    else:
        buf = input_img.copy()

    if contrast != 0:
        f = 131*(contrast + 127)/(127*(131-contrast))
        alpha_c = f
        gamma_c = 127*(1-f)

        buf = cv2.addWeighted(buf, alpha_c, buf, 0, gamma_c)

    return buf


font = cv2.FONT_HERSHEY_SIMPLEX
fcolor = (0,0,0)

blist = [0, -127, 127,   0,  0, 64] # list of brightness values
clist = [0,    0,   0, -64, 64, 64] # list of contrast values


out = np.zeros((s*2, s*3, 3), dtype = np.uint8)

for i, b in enumerate(blist):
    c = clist[i]
    print('b, c:  ', b,', ',c)
    row = s*int(i/3)
    col = s*(i%3)

    print('row, col:   ', row, ', ', col)

    out[row:row+s, col:col+s] = apply_brightness_contrast(img, b, c)
    msg = 'b %d' % b
    cv2.putText(out,msg,(col,row+s-22), font, .7, fcolor,1,cv2.LINE_AA)
    msg = 'c %d' % c
    cv2.putText(out,msg,(col,row+s-4), font, .7, fcolor,1,cv2.LINE_AA)

    cv2.putText(out, 'OpenCV',(260,30), font, 1.0, fcolor,2,cv2.LINE_AA)

cv2.imwrite('out.png', out)

enter image description here

J'ai traité manuellement les images dans GIMP et ajouté des balises de texte en Python/OpenCV:
enter image description here

Remarque: @UtkarshBhardwaj a suggéré que Python 2.x doivent convertir le code de calcul de correction de contraste en float pour obtenir résultat flottant, comme ceci:

...
if contrast != 0:
        f = float(131*(contrast + 127))/(127*(131-contrast))
...
15
bfris

La luminosité et le contraste peuvent être ajustés en utilisant respectivement alpha (α) Et bêta (β). L'expression peut s'écrire

enter image description here

OpenCV implémente déjà cela comme cv2.convertScaleAbs() , il suffit de fournir les valeurs définies par l'utilisateur alpha et beta

import cv2

image = cv2.imread('1.jpg')

alpha = 1.5 # Contrast control (1.0-3.0)
beta = 0 # Brightness control (0-100)

adjusted = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)

cv2.imshow('original', image)
cv2.imshow('adjusted', adjusted)
cv2.waitKey()

Avant -> Après

enter image description hereenter image description here

Remarque: Pour le réglage automatique de la luminosité/du contraste, consultez réglage automatique du contraste et de la luminosité d'une photo couleur

8
nathancy

La meilleure explication pour X = aY + b (En fait, c'est f(x) = ax + b)) est fournie à https://math.stackexchange.com/a/906280/357701

Un plus simple en ajustant simplement la luminosité/luma/luminosité pour le contraste comme ci-dessous:

import cv2

img = cv2.imread('test.jpg')
cv2.imshow('test', img)
cv2.waitKey(1000)
imghsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)


imghsv[:,:,2] = [[max(pixel - 25, 0) if pixel < 190 else min(pixel + 25, 255) for pixel in row] for row in imghsv[:,:,2]]
cv2.imshow('contrast', cv2.cvtColor(imghsv, cv2.COLOR_HSV2BGR))
cv2.waitKey(1000)
raw_input()
5
be_good_do_good