Soy nuevo en Python OpenCV. He leído algunos documentos y respuestas aquí pero soy incapaz de averiguar lo que significa el siguiente código:
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)
He llegado a saber que Básicamente, cada píxel puede ser transformado como X = aY + b donde a y b son escalares.
. Básicamente, he entendido esto. Sin embargo, no he entendido el código y cómo aumentar el contraste con esto.
Hasta ahora, he conseguido simplemente leer la imagen usando img = cv2.imread('image.jpg',0)
.
Gracias por vuestra ayuda
Me gustaría sugerir un método que utiliza el canal de color LAB. Wikipedia tiene suficiente información con respecto a lo que el canal de color LAB se trata.
He hecho lo siguiente usando OpenCV 3.0.0 y 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_____#
Puedes ejecutar el código tal cual. Para saber en qué consiste CLAHE (Contrast Limited Adaptive Histogram Equalization)puedes consultar de nuevo la Wikipedia.
El núcleo de la respuesta original se conserva en la nota de abajo \\
Para Python, no he encontrado una función OpenCV que proporciona contraste. Como otros han sugerido, hay algunas técnicas para aumentar automáticamente el contraste.
En los docs oficiales de OpenCV, se sugiere que esta ecuación puede ser usada para aplicar contraste y brillo al mismo tiempo: nueva_imagen = alfa*vieja_imagen + beta
donde alfa corresponde a un contraste y beta es el brillo. Diferentes casos
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++, puedes implementar esta ecuación usando cv::Mat::convertTo, pero no tenemos acceso a esa parte de la librería desde Python. Para hacerlo en Python, recomendaría usar la función cv::addWeighted, porque es rápida y fuerza automáticamente a que la salida esté en el rango de 0 a 255 (por ejemplo, para una imagen en color de 24 bits, 8 bits por 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
Nota de inicio<<<<<
Como originalmente publicado, me refería a esta fórmula de este libro en línea GIMP](http://pippin.gimp.org/image_processing/chap_point.html) es
nueva_imagen = (antigua_imagen - 0.5) × contraste + 0.5
y esta fórmula modificada para cambiar la escala de contraste para ir de -127 a +127:
nueva_imagen = (antigua_imagen) × (contraste/127 + 1) - contraste
Estas fórmulas tanto el rendimiento de brillo y contraste cambios, pero tienen los puntos débiles:
Nota final<<<<<
De aquí en adelante, trataré de reproducir el comportamiento generalmente visto en los programas de edición de fotos y específicamente el comportamiento en el GIMP.
En el GIMP, los niveles de contraste van de -127 a +127. He adaptado las fórmulas de aquí para que se ajusten a ese rango.
f = 131(contraste + 127)/(127(131-contraste)) nueva_imagen = f(antigua_imagen - 127) + 127 = f(antigua_imagen) + 127*(1-f)
Para calcular el brillo, he averiguado la relación entre el brillo y los niveles y he utilizado la información de este post sobre niveles para llegar a una solución.
#pseudo code
if brightness > 0
shadow = brightness
highlight = 255
else:
shadow = 0
highlight = 255 + brightness
new_img = ((highlight - shadow)/255)*old_img + shadow
Poniendo todo junto y añadiendo usando la imagen de referencia "mandrill" de USC 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)
Procesé manualmente las imágenes en el GIMP y añadí etiquetas de texto en Python/OpenCV:
Nota: @UtkarshBhardwaj ha sugerido que los usuarios de Python 2.x deben convertir el código de cálculo de corrección de contraste en float para obtener un resultado flotante, así:
...
if contrast != 0:
f = float(131*(contrast + 127))/(127*(131-contrast))
...
La mejor explicación de X = aY + b
(de hecho, f(x) = ax + b
) se encuentra en https://math.stackexchange.com/a/906280/357701.
Una más simple con sólo ajustar la luminosidad/luma/brillo para el contraste como se muestra a continuación:
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()