web-dev-qa-db-fra.com

Quel est le moyen le plus rapide d'augmenter le contraste des images couleur avec OpenCV en python (cv2)?

J'utilise OpenCV pour traiter certaines images, et l'une des premières étapes que je dois effectuer consiste à augmenter le contraste de l'image sur une image couleur. La méthode la plus rapide que j'ai trouvée jusqu'à présent utilise ce code (où np est l'importation numpy) pour se multiplier et ajouter comme suggéré dans le cv1 basé sur C d'origine :

    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)  

Y at-il un moyen plus rapide de faire cela en Python? J’ai essayé d’utiliser la multiplication scalaire de numpy à la place, mais les performances sont en réalité pires. J'ai aussi essayé d'utiliser cv2.convertScaleAbs (les documents OpenCV suggéraient d'utiliser convertTo, mais cv2 semble ne pas disposer d'une interface pour cette fonction), mais là encore, les performances ont été pires en test. 

11
Todd Stellanova

L'arithmétique simple dans les tableaux numpy est la plus rapide, a commenté Abid Rahaman K. 

Utilisez cette image par exemple: http://i.imgur.com/Yjo276D.png

Voici un peu de traitement d'image qui ressemble à la manipulation de luminosité/contraste:

'''
Simple and fast image transforms to mimic:
 - brightness
 - contrast
 - erosion 
 - dilation
'''

import cv2
from pylab import array, plot, show, axis, arange, figure, uint8 

# Image data
image = cv2.imread('imgur.png',0) # load as 1-channel 8bit grayscale
cv2.imshow('image',image)
maxIntensity = 255.0 # depends on dtype of image data
x = arange(maxIntensity) 

# Parameters for manipulating image data
phi = 1
theta = 1

# Increase intensity such that
# dark pixels become much brighter, 
# bright pixels become slightly bright
newImage0 = (maxIntensity/phi)*(image/(maxIntensity/theta))**0.5
newImage0 = array(newImage0,dtype=uint8)

cv2.imshow('newImage0',newImage0)
cv2.imwrite('newImage0.jpg',newImage0)

y = (maxIntensity/phi)*(x/(maxIntensity/theta))**0.5

# Decrease intensity such that
# dark pixels become much darker, 
# bright pixels become slightly dark 
newImage1 = (maxIntensity/phi)*(image/(maxIntensity/theta))**2
newImage1 = array(newImage1,dtype=uint8)

cv2.imshow('newImage1',newImage1)

z = (maxIntensity/phi)*(x/(maxIntensity/theta))**2

# Plot the figures
figure()
plot(x,y,'r-') # Increased brightness
plot(x,x,'k:') # Original image
plot(x,z, 'b-') # Decreased brightness
#axis('off')
axis('tight')
show()

# Close figure window and click on other window 
# Then press any keyboard key to close all windows
closeWindow = -1
while closeWindow<0:
    closeWindow = cv2.waitKey(1) 
cv2.destroyAllWindows()

Image originale en niveaux de gris:

enter image description here

Image éclairée qui semble être dilatée:

enter image description here

Image assombrie qui semble être érodée, accentuée, avec un meilleur contraste:

enter image description here

Comment les intensités de pixels sont transformées:

enter image description here

Si vous jouez avec les valeurs de phi et theta, vous pouvez obtenir des résultats vraiment intéressants. Vous pouvez également implémenter cette astuce pour les données d'image multicanal. 

--- MODIFIER ---

jetez un coup d’œil aux concepts de 'niveaux' et de 'courbes' sur cette vidéo sur youtube montrant l’édition d’images dans photoshop. L’équation de la transformation linéaire crée le même montant, c’est-à-dire le «niveau» de changement pour chaque pixel. Si vous écrivez une équation qui permet de distinguer les types de pixels (par exemple, ceux qui ont déjà une certaine valeur), vous pouvez modifier les pixels en fonction de la «courbe» décrite par cette équation.

16
samkhan13

Essayez ce code:

import cv2

img = cv2.imread('sunset.jpg', 1)
cv2.imshow("Original image",img)

# CLAHE (Contrast Limited Adaptive Histogram Equalization)
clahe = cv2.createCLAHE(clipLimit=3., tileGridSize=(8,8))

lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)  # convert from BGR to LAB color space
l, a, b = cv2.split(lab)  # split on 3 different channels

l2 = clahe.apply(l)  # apply CLAHE to the L-channel

lab = cv2.merge((l2,a,b))  # merge channels
img2 = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)  # convert from LAB to BGR
cv2.imshow('Increased contrast', img2)
#cv2.imwrite('sunset_modified.jpg', img2)

cv2.waitKey(0)
cv2.destroyAllWindows()

Coucher de soleil avant:  enter image description here Coucher de soleil après augmentation du contraste:  enter image description here

9
foo bar

Utilisez la fonction cv :: addWeighted . Il est conçu pour travailler sur deux images

dst = cv.addWeighted (src1, alpha, src2, bêta, gamma [ dst [ dtype]])

Mais si vous utilisez la même image deux fois ET que vous définissez la bêta à zéro, vous pouvez obtenir l'effet souhaité.

dst = cv.addWeighed (src1, alpha, src1, 0, gamma)

Le gros avantage de l’utilisation de cette fonction est que vous n’aurez plus à vous soucier de ce qui se passe lorsque les valeurs sont inférieures à 0 ou supérieures à 255. Dans Numpy, vous devez trouver un moyen de réaliser tout le découpage vous-même. En utilisant la fonction OpenCV, il effectue tout le découpage pour vous et c'est rapide. 

0
bfris