Как увеличить контраст изображения в Python OpenCV
Я новичок в Python OpenCV. Я прочитал некоторые документы и ответы здесь, но я не могу понять, что означает следующий код:
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)
Я узнал, что Basically, every pixel can be transformed as X = aY + b where a and b are scalars.
, По сути, я это понял. Однако я не понял код и как увеличить контраст с этим.
До сих пор мне удалось просто прочитать изображение с помощью img = cv2.imread('image.jpg',0)
Спасибо за вашу помощь
7 ответов
Я хотел бы предложить метод с использованием цветового канала LAB. В Википедии достаточно информации о том, что такое цветной канал LAB.
Я сделал следующее, используя OpenCV 3.0.0 и 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_____#
Вы можете запустить код как есть. Чтобы узнать, что такое CLAHE (адаптивная эквалайзерная ограниченная гистограмма), вы можете снова просмотреть Википедию.
\\ это сообщение было сильно отредактировано от оригинала. ядро исходного ответа сохраняется в примечании ниже \\
Для Python я не нашел функцию OpenCV, которая обеспечивает контраст. Как и предполагали другие, есть некоторые методы для автоматического увеличения контраста.
В официальных документах OpenCV предлагается использовать это уравнение для одновременного применения контрастности и яркости:
new_img = alpha * old_img + beta
где альфа соответствует контрасту, а бета - яркости. Разные случаи
alpha 1 beta 0 --> no change
0 < alpha < 1 --> lower contrast
alpha > 1 --> higher contrast
-127 < beta < +127 --> good range for brightness values
В C/C++ вы можете реализовать это уравнение, используя cv::Mat::convertTo, но у нас нет доступа к этой части библиотеки из Python. Чтобы сделать это в Python, я бы порекомендовал использовать функцию cv::addWeighted, потому что она быстра и автоматически вынуждает выходной сигнал находиться в диапазоне от 0 до 255 (например, для 24-битного цветного изображения, 8 бит на канал).
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
>>>>> Начать заметку<<<<<
В первоначальном виде я ссылался на эту формулу из этой онлайновой книги GIMP] ( http://pippin.gimp.org/image_processing/chap_point.html)
new_image = (old_image - 0.5) × контрастность + 0.5
и эта модифицированная формула для изменения контрастной шкалы с -127 на +127:
new_image = (old_image) × (контраст /127 + 1) - контраст
Эти формулы приведут к изменениям яркости и контрастности, но у них есть недостатки:
- вторая формула не является строго полученной из первой
- они не соответствуют яркости и контрастности, наблюдаемым в других программах (например, PhotoShop, GIMP и т. д.)
>>>>> Конец заметки<<<<<
С этого момента я постараюсь воспроизвести поведение, обычно наблюдаемое в программах для редактирования фотографий, и, в частности, поведение в GIMP.
контрастировать
В GIMP уровни контрастности варьируются от -127 до +127. Я адаптировал формулы отсюда, чтобы соответствовать этому диапазону.
f = 131 * (контраст + 127)/(127*(131-контраст))
new_image = f * (old_image - 127) + 127 = f * (old_image) + 127 * (1-f)
Чтобы выяснить яркость, я выяснил соотношение между яркостью и уровнями и использовал информацию в этом посте уровней, чтобы прийти к решению.
#pseudo code
if brightness > 0
shadow = brightness
highlight = 255
else:
shadow = 0
highlight = 255 + brightness
new_img = ((highlight - shadow)/255)*old_img + shadow
яркость и контрастность в Python и OpenCV
Собираем все вместе и добавляем, используя эталонное изображение "mandrill" из 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)
Я вручную обработал изображения в GIMP и добавил текстовые теги в Python/OpenCV:
Яркость и контраст можно регулировать с помощью альфа (α
) и бета (β
) соответственно. Выражение можно записать как
OpenCV уже реализует это как cv2.convertScaleAbs()
, просто предоставьте определяемый пользователем alpha
а также 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()
Перед ->
После
Примечание. Для автоматической регулировки яркости / контрастности обратите внимание на автоматическую настройку контрастности и яркости цветной фотографии.
Здесь довольно много ответов, от простых до сложных. Я хочу добавить еще одну, более простую, которая кажется немного более практичной для фактических настроек контрастности и яркости.
def adjust_contrast_brightness(img, contrast:float=1.0, brightness:int=0):
"""
Adjusts contrast and brightness of an uint8 image.
contrast: (0.0, inf) with 1.0 leaving the contrast as is
brightness: [-255, 255] with 0 leaving the brightness as is
"""
brightness += int(round(255*(1-contrast)/2))
return cv2.addWeighted(img, contrast, img, 0, brightness)
Мы делаем
a*x+b
регулировка через
addWeighted()
функция. Однако, чтобы изменить контраст без изменения яркости, данные должны быть центрированы по нулю. Это не относится к типу данных uint8 по умолчанию OpenCV. Таким образом, нам также необходимо настроить яркость в соответствии с тем, как смещается распределение.
Лучшее объяснение для X = aY + b
(на самом деле это f(x) = ax + b
)) предоставляется по адресу /questions/3186088/v-aspnet-luchshe-hranit-zagruzhennyij-fajl-v-relyatsionnoj-baze-dannyih-ili-pomestit-ego-v-fajlovuyu-sistemu/3186093#3186093
Проще, просто отрегулировав яркость / яркость / яркость для контраста, как показано ниже:
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()
img = cv2.imread("/x2.jpeg")
image = cv2.resize(img, (1800, 1800))
alpha=1.5
beta=20
new_image=cv2.addWeighted(image,alpha,np.zeros(image.shape, image.dtype),0,beta)
cv2.imshow("new",new_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
Ссылка из описания ссылки здесь
Нам необходимо рассчитать коэффициент коррекции контрастности, заданный по формуле ниже.
Чтобы алгоритм работал правильно, значение коэффициента коррекции контраста ( F ) должно храниться как число с плавающей запятой, а не целое число. Значение C в формуле указывает желаемый уровень контрастности.
Следующим шагом будет выполнение самой регулировки контрастности. Следующая формула показывает корректировку контрастности красного компонента цвета:
Функция усечения только гарантирует, что новые значения красного, зеленого и синего находятся в допустимом диапазоне от 0 до 255.
Значение контрастности будет находиться в диапазоне от -255 до +255. Отрицательные значения уменьшают контрастность, и наоборот, положительные значения увеличивают контрастность.
Здесь вы устанавливаете контрастность -128 (уменьшение) и +128 (увеличение).
import cv2
import matplotlib.pyplot as plt
image = cv2.imread("lena.jpg")
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
imageContrast = image.copy()
height, width, _ = image.shape
def truncate(value):
if value < 0:
return 0
elif value > 255:
return 255
else:
return value
def adjustContrast(pixel, contrast=0):
b, g, r = pixel
f = (259 * (contrast + 255)) / (255 * (259 - contrast))
bNew = (int)(truncate(f * (b - 128) + 128))
gNew = (int)(truncate(f * (r - 128) + 128))
rNew = (int)(truncate(f * (r - 128) + 128))
return bNew, gNew, rNew
clist = [-128, 128]
plt.subplot(1, len(clist) + 1, 1)
plt.title("Orjinal")
plt.imshow(image)
plt.xticks([])
plt.yticks([])
for index, contrast in enumerate(clist):
for i in range(width):
for j in range(height):
_b, _g, _r = adjustContrast(image[j, i], clist[index])
imageContrast[j, i] = [_b, _g, _r]
plt.subplot(1, len(clist) + 1, index + 2)
plt.title("Contrast:" + str(contrast))
plt.imshow(imageContrast)
plt.xticks([])
plt.yticks([])
plt.show()