Используйте OpenCV, Numpy для расчета гистограммы, Matplot для рисования гистограммы и анализа
В этом блоге рассказывается, как использовать функции Python, OpenCV, Numpy для расчета гистограмм, а также использовать функции OpenCV и Matplotlib для рисования и анализа гистограмм.
Просматривая гистограмму изображения, вы можете интуитивно понять контрастность, яркость, распределение интенсивности и т. д. изображения.
1. Рендеринг
Исходное изображение выглядит следующим образом:
Эффект гистограммы в оттенках серого выглядит следующим образом:
Вы можете видеть, что область слева показывает количество более темных пикселей в изображении, а область справа показывает количество более светлых пикселей. Из гистограммы видно, что темных участков, светлых участков не много, а количество полутонов (значения пикселей в среднем диапазоне, например, около 170/210) очень велико.
Эффект гистограммы трех каналов BGR выглядит следующим образом: Исходное изображение VS Mask mask VS Mask image VS смешанная гистограмма выглядит следующим образом:На 4-й гистограмме синяя линия представляет собой гистограмму полного изображения, а красная линия — гистограмму замаскированной области.
2. Принцип
Гистограмма может помочь получить полное представление о распределении интенсивности изображения.Самая простая гистограмма представляет собой гистограмму изображения в градациях серого, график со значениями пикселей (в диапазоне от 0 до 255) по оси x и соответствующим количеством пикселей в изображении по оси y.
3 способа расчета гистограммы:
- hist = cv2.calcHist([img],[0],None,[256],[0,256])
- hist,bins = np.histogram(img.ravel(),256,[0,256])
- np.bincount(img.ravel(),minlength=256)
Метод cv2 в 40 раз быстрее, чем np.histogram;
np.bincount в 10 раз быстрее, чем np.histogram, поэтому предпочтительным является метод cv2.calHist();
2 способа нарисовать гистограмму:
- matplot вычисляет гистограмму и рисует ее: plt.hist(img.ravel(),256,[0,256]); plt.show()
- Простой метод рисования матплота: histr = cv2.calcHist([img],[i],None,[256],[0,256]) plt.plot (истр, цвет = столбец) plt.xlim([0,256])
3. Исходный код
3.1 3 метода расчета и 2 метода построения гистограммы
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('ml.jpg', 0)
# cv计算直方图
# cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
# - img:要计算直方图的图像
# - channels:通道值,如果传入灰度图为0,彩色图[0][1][2]分别计算BGR通道
# - mask:蒙版,并非为整个图计算直方图
# - histSize:x轴分多少个范围
# - ranges: 值的范围,通常是[0,256]
hist = cv2.calcHist([img], [0], None, [256], [0, 256])
# numpy计算直方图
# np.bincount() 比 np.histogram() 大概快10倍
# cv2.calHist() 比 np.histogram() 大概快40倍
hist, bins = np.histogram(img.ravel(), 256, [0, 256])
hist = np.bincount(img.ravel(), minlength=256)
# 绘制直方图法1:matplot
img = cv2.imread('ml.jpg', 0)
plt.hist(img.ravel(), 256, [0, 256])
plt.show()
# 绘制直方图法2:matplot普通绘制方式
img = cv2.imread('ml.jpg')
color = ('b', 'g', 'r')
for i, col in enumerate(color):
histr = cv2.calcHist([img], [i], None, [256], [0, 256])
plt.plot(histr, color=col)
plt.xlim([0, 256])
plt.show()
3.2 Гистограмма изображения маски
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('ml.jpg', 0)
# 构造一个mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv2.bitwise_and(img, img, mask=mask)
# 计算整个图直方图以及mask的直方图
hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])
plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask, 'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full, color='b'), plt.plot(hist_mask, color='r')
plt.xlim([0, 256])
plt.show()