Код, который вы написали, выполняет логарифмическое преобразование, применяемое к интенсивностям изображения. Причина, по которой вы получаете такую высокую паразитную интенсивность, как максимум, потому что ваши петли for
ошибочны. В частности, ваш range
неверен. range
является эксклюзивный периода окончания, что означает, что вы должны пойти до img.shape[0]
и img.shape[1]
соответственно, а не img.shape[0]-1
или img.shape[1]-1
. Поэтому вам не хватает последней строки и последнего столбца изображения, и они не затрагиваются логарифмической операцией. Максимум, о котором сообщается, относится к одному из этих пикселей в последней строке или столбце, которые вы не касались.
После того, как вы это исправить, вы не получите эти плохие интенсивности больше:
for i in range(0,img2.shape[0]): # Change
for j in range(0,img2.shape[1]): # Change
if (math.log(1+img2[i,j],2)) < 0:
img2[i,j]=0
else:
img2[i,j] = np.int(math.log(1+img2[i,j],2))
Doing что теперь дает нам:
('Maximum intensity = ', 7)
('minimum intensity = ', 0)
Однако то, что вы собираетесь получить сейчас очень темное изображение. Гистограмма, которую вы показали нам, иллюстрирует, что все пиксели изображения находятся в темном диапазоне ... примерно между [0-7]
. Из-за этого большая часть вашего изображения будет темной, если вы используете uint8
в качестве типа данных для визуализации. Примите к сведению, что я искал для изображения Лионель Месси, который является частью из OpenCV учебники, и это изображение, которое я нашел:
Источник: https://opencv-python-tutroals.readthedocs.org/en/latest/_images/roi.jpg
Ваш код преобразования это в оттенках серого , и это хорошо для вашего вопроса. Теперь, используя вышеупомянутое изображение, если вы на самом деле показать, что граф гистограммы выглядит так же, как то, что Интенсивности в бункер в гистограмме, это то, что мы получаем для img2
:
In [41]: np.unique(img2)
Out[41]: array([0, 1, 2, 3, 4, 5, 6, 7], dtype=uint8)
In [42]: np.bincount(img2.ravel())
Out[42]: array([ 86, 88, 394, 3159, 14841, 29765, 58012, 19655])
Как вы можете видеть, основная часть пикселей изображения колеблется между диапазоном [0-7]
, поэтому все выглядит черным.Если вы хотите увидеть это лучше, возможно масштабировать изображение примерно 255/7 = 36
или таким образом, мы можем видеть изображение лучше:
img2 = 36*img2
cv2.imshow('LSP',img2)
cv2.waitKey(0)
Мы получаем этот образ:
Я также получить эту гистограмму :
Это лично выглядит очень некрасиво ... по крайней мере, для меня. Таким образом, я бы рекомендовал вам выбрать более значимое преобразование изображения, если вы хотите растянуть гистограмму. Фактически операция log
сжимает динамический диапазон гистограммы. Если вы хотите растянуть гистограмму, пройдите противоположным способом и попробуйте операцию степеней. В частности, с учетом интенсивности входного сигнала и выходной сигнал определяется как:
out = c*in^(p)
in
является интенсивностью входного сигнала, p
является силой и c
является константой для того, чтобы масштабировать изображение таким образом, что максимальная интенсивность получает отображается на та же максимальная интенсивность ввода, когда вы закончите, и ничего больше. Это может быть сделано путем вычисления c
так, что:
c = (img2.max())/(img2.max()**p)
... где p
сила вы хотите. Кроме того, преобразование с помощью степенного закона можно объяснить с этой хорошей диаграммой:
Источник: http://www.nptel.ac.in/courses/117104069/chapter_8/8_14.html
В принципе, полномочия, которые меньше, чем 1 выполнить разложение интенсивности где более темные интенсивности получить толчок к более светлой стороне. Аналогично, мощности, которые больше 1, выполняют сжатие интенсивности, когда более легкие интенсивности попадают в более темную сторону. В вашем случае вы хотите развернуть гистограмму, и поэтому вы хотите первый вариант. В частности, попробуйте сделать меньшие интенсивности, направленные на более широкий диапазон. Это можно сделать, выбирая мощность, которая меньше 1 ... например, попробуйте 0,5.
Вы хотите изменить свой код так, чтобы это так:
img2 = img2.astype(np.float) # Cast to float
c = (img2.max())/(img2.max()**(0.5))
for i in range(0,img2.shape[0]-1):
for j in range(0,img2.shape[1]-1):
img2[i,j] = np.int(c*img2[i,j]**(0.5))
# Cast back to uint8 for display
img2 = img2.astype(np.uint8)
Делая это, я получаю это изображение:
Я также получаю эту гистограмму:
Minor Примечание
Если я могу предложить что-то с точки зрения эффективности, я бы не рекомендовал вам цикл по всему изображению и установите каждый пиксель индивидуально ... вот как numpy
массивы были не должны быть используемый. Вы можете добиться того, что вы хотите использовать в одной строке кода.
С вашим старым кодом, используйте np.log2
, не math.log
с основанием 2 с numpy
массивами:
import cv2
import numpy as np
from matplotlib import pyplot as plt
# Your code
img = cv2.imread('messi.jpg',0)
# New code
img2 = np.log2(1 + img.astype(np.float)).astype(np.uint8)
# Back to your code
img2 = 36*img2 # Edit from before
cv2.imshow('LSP',img2)
cv2.waitKey(0)
fig = plt.gcf()
fig.canvas.set_window_title('LSP histogram')
plt.hist(img2.ravel(),256,[0,256]); plt.show()
img3 = img2
B = np.int(img3.max())
A = np.int(img3.min())
print ("Maximum intensity = ", B)
print ("minimum intensity = ", A)
cv2.destroyAllWindows() # Don't forget this
Точно так же, если вы хотите применить преобразование степенного, это очень просто:
import cv2
import numpy as np
from matplotlib import pyplot as plt
# Your code
img = cv2.imread('messi.jpg',0)
# New code
c = (img2.max())/(img2.max()**(0.5))
img2 = (c*img.astype(np.float)**(0.5)).astype(np.uint8)
#... rest of code as before
@Miki img3 = img2 – zinon