图像区域的直方图
Histogram of a region of an image
我想获取 python 中 numpy 图像中某个区域的直方图。我找到了一个关于如何使用面具的解决方案 here.
此解决方案对我没有帮助,因为如果我使用它,我将丢失实际数量的黑色像素。另外,我想要得到的区域不一定是矩形的。
要计算直方图,请使用 np.histogram
函数。它 returns 一个直方图和分箱。因此您可以存储结果并使用它:
hist, bins = np.histogram(arr, bins=bins, range=range)
如果要绘制结果,可以在应用 np.histogram
后使用 plt.bar
,只需传递 bins
和 hist
:
plt.bar(bins, hist)
另一个选项是使用 matplotlib
plt.hist
它计算直方图并根据原始数据绘制它:
plt.hist(arr, bins=bins)
以下是任意形状图像区域直方图的完整示例:
代码:
import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import face
from PIL import Image, ImageDraw
# Let's create test image with different colors
img = np.zeros((300, 300, 3), dtype=np.uint8)
img[0:150, 0:150] = [255, 0, 0]
img[0:150, 150:] = [0, 255, 0]
img[150:, :150] = [0, 0, 255]
img[150:, 150:] = [255, 255, 255]
# define our function for preparing mask
def prepare_mask(polygon, image):
"""Returns binary mask based on input polygon presented as list of coordinates of vertices
Params:
polygon (list) - coordinates of polygon's vertices. Ex: [(x1,y1),(x2,y2),...] or [x1,y1,x2,y2,...]
image (numpy array) - original image. Will be used to create mask of the same size. Shape (H, W, C).
Output:
mask (numpy array) - boolean mask. Shape (H, W).
"""
# create an "empty" pre-mask with the same size as original image
width = image.shape[1]
height = image.shape[0]
mask = Image.new('L', (width, height), 0)
# Draw your mask based on polygon
ImageDraw.Draw(mask).polygon(polygon, outline=1, fill=1)
# Covert to np array
mask = np.array(mask).astype(bool)
return mask
def compute_histogram(mask, image):
"""Returns histogram for image region defined by mask for each channel
Params:
image (numpy array) - original image. Shape (H, W, C).
mask (numpy array) - boolean mask. Shape (H, W).
Output:
list of tuples, each tuple (each channel) contains 2 arrays: first - computed histogram, the second - bins.
"""
# Apply binary mask to your array, you will get array with shape (N, C)
region = image[mask]
red = np.histogram(region[..., 0].ravel(), bins=256, range=[0, 256])
green = np.histogram(region[..., 1].ravel(), bins=256, range=[0, 256])
blue = np.histogram(region[..., 2].ravel(), bins=256, range=[0, 256])
return [red, green, blue]
def plot_histogram(histograms):
"""Plots histogram computed for each channel.
Params:
histogram (list of tuples) - [(red_ch_hist, bins), (green_ch_hist, bins), (green_ch_hist, bins)]
"""
colors = ['r', 'g', 'b']
for hist, ch in zip(histograms, colors):
plt.bar(hist[1][:256], hist[0], color=ch)
# Create some test masks
red_polygon = [(50, 100), (50, 50), (100, 75)]
green_polygon = [(200, 100), (200, 50), (250, 75)]
blue_polygon = [(50, 250), (50, 200), (100, 225)]
white_polygon = [(200, 250), (200, 200), (250, 225)]
polygons = [red_polygon, green_polygon, blue_polygon, white_polygon]
for polygon in polygons:
mask = prepare_mask(polygon, img)
histograms = compute_histogram(mask, img)
# Let's plot our test results
plt.figure(figsize=(10, 10))
plt.subplot(221)
plt.imshow(img)
plt.title('Image')
plt.subplot(222)
plt.imshow(mask, cmap='gray')
plt.title('Mask')
plt.subplot(223)
plot_histogram(histograms)
plt.title('Histogram')
plt.show()
输出:
浣熊的最终测试:
代码:
raccoon = face()
polygon = [(200, 700), (150, 600), (300, 500), (300, 400), (400, 500)]
mask = prepare_mask(polygon, raccoon)
histograms = compute_histogram(mask, raccoon)
plt.figure(figsize=(10, 10))
plt.subplot(221)
plt.imshow(raccoon)
plt.title('Image')
plt.subplot(222)
plt.imshow(mask, cmap='gray')
plt.title('Mask')
plt.subplot(223)
plot_histogram(histograms)
plt.title('Histogram')
plt.show()
输出:
让我们定义(x,y)
5个点的坐标(p0, p1, p2, p3, p4)
作为区域的角点。在将点连接为 np 数组后,我们可以使用 opencv fillPoly
函数制作一个掩码。可以使用此掩码过滤图像的像素值。我使用 matplotlib 的直方图。 Opencv和numpy也有直方图函数。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img_x = img.copy()
pts = np.concatenate((p0, p1, p2, p3, p4)).reshape((-1, 1, 2))
cv2.fillPoly(img_x , [pts], (255, 255, 255))
n, bins, patches = plt.hist(img[img_x == (255, 255, 255)], 256, [0, 256])
我想获取 python 中 numpy 图像中某个区域的直方图。我找到了一个关于如何使用面具的解决方案 here.
此解决方案对我没有帮助,因为如果我使用它,我将丢失实际数量的黑色像素。另外,我想要得到的区域不一定是矩形的。
要计算直方图,请使用 np.histogram
函数。它 returns 一个直方图和分箱。因此您可以存储结果并使用它:
hist, bins = np.histogram(arr, bins=bins, range=range)
如果要绘制结果,可以在应用 np.histogram
后使用 plt.bar
,只需传递 bins
和 hist
:
plt.bar(bins, hist)
另一个选项是使用 matplotlib
plt.hist
它计算直方图并根据原始数据绘制它:
plt.hist(arr, bins=bins)
以下是任意形状图像区域直方图的完整示例:
代码:
import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import face
from PIL import Image, ImageDraw
# Let's create test image with different colors
img = np.zeros((300, 300, 3), dtype=np.uint8)
img[0:150, 0:150] = [255, 0, 0]
img[0:150, 150:] = [0, 255, 0]
img[150:, :150] = [0, 0, 255]
img[150:, 150:] = [255, 255, 255]
# define our function for preparing mask
def prepare_mask(polygon, image):
"""Returns binary mask based on input polygon presented as list of coordinates of vertices
Params:
polygon (list) - coordinates of polygon's vertices. Ex: [(x1,y1),(x2,y2),...] or [x1,y1,x2,y2,...]
image (numpy array) - original image. Will be used to create mask of the same size. Shape (H, W, C).
Output:
mask (numpy array) - boolean mask. Shape (H, W).
"""
# create an "empty" pre-mask with the same size as original image
width = image.shape[1]
height = image.shape[0]
mask = Image.new('L', (width, height), 0)
# Draw your mask based on polygon
ImageDraw.Draw(mask).polygon(polygon, outline=1, fill=1)
# Covert to np array
mask = np.array(mask).astype(bool)
return mask
def compute_histogram(mask, image):
"""Returns histogram for image region defined by mask for each channel
Params:
image (numpy array) - original image. Shape (H, W, C).
mask (numpy array) - boolean mask. Shape (H, W).
Output:
list of tuples, each tuple (each channel) contains 2 arrays: first - computed histogram, the second - bins.
"""
# Apply binary mask to your array, you will get array with shape (N, C)
region = image[mask]
red = np.histogram(region[..., 0].ravel(), bins=256, range=[0, 256])
green = np.histogram(region[..., 1].ravel(), bins=256, range=[0, 256])
blue = np.histogram(region[..., 2].ravel(), bins=256, range=[0, 256])
return [red, green, blue]
def plot_histogram(histograms):
"""Plots histogram computed for each channel.
Params:
histogram (list of tuples) - [(red_ch_hist, bins), (green_ch_hist, bins), (green_ch_hist, bins)]
"""
colors = ['r', 'g', 'b']
for hist, ch in zip(histograms, colors):
plt.bar(hist[1][:256], hist[0], color=ch)
# Create some test masks
red_polygon = [(50, 100), (50, 50), (100, 75)]
green_polygon = [(200, 100), (200, 50), (250, 75)]
blue_polygon = [(50, 250), (50, 200), (100, 225)]
white_polygon = [(200, 250), (200, 200), (250, 225)]
polygons = [red_polygon, green_polygon, blue_polygon, white_polygon]
for polygon in polygons:
mask = prepare_mask(polygon, img)
histograms = compute_histogram(mask, img)
# Let's plot our test results
plt.figure(figsize=(10, 10))
plt.subplot(221)
plt.imshow(img)
plt.title('Image')
plt.subplot(222)
plt.imshow(mask, cmap='gray')
plt.title('Mask')
plt.subplot(223)
plot_histogram(histograms)
plt.title('Histogram')
plt.show()
输出:
浣熊的最终测试:
代码:
raccoon = face()
polygon = [(200, 700), (150, 600), (300, 500), (300, 400), (400, 500)]
mask = prepare_mask(polygon, raccoon)
histograms = compute_histogram(mask, raccoon)
plt.figure(figsize=(10, 10))
plt.subplot(221)
plt.imshow(raccoon)
plt.title('Image')
plt.subplot(222)
plt.imshow(mask, cmap='gray')
plt.title('Mask')
plt.subplot(223)
plot_histogram(histograms)
plt.title('Histogram')
plt.show()
输出:
让我们定义(x,y)
5个点的坐标(p0, p1, p2, p3, p4)
作为区域的角点。在将点连接为 np 数组后,我们可以使用 opencv fillPoly
函数制作一个掩码。可以使用此掩码过滤图像的像素值。我使用 matplotlib 的直方图。 Opencv和numpy也有直方图函数。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img_x = img.copy()
pts = np.concatenate((p0, p1, p2, p3, p4)).reshape((-1, 1, 2))
cv2.fillPoly(img_x , [pts], (255, 255, 255))
n, bins, patches = plt.hist(img[img_x == (255, 255, 255)], 256, [0, 256])