图像区域的直方图

时间:2018-12-25 16:12:44

标签: python numpy opencv image-processing roi

我想在python的numpy图片中获取区域的组织学信息。我找到了有关如何使用遮罩here.

的解决方案

此解决方案没有帮助我,因为如果使用它,我会丢失黑色像素的实际数量。另外,我要获得的区域不一定是矩形。

1 个答案:

答案 0 :(得分:4)

要计算直方图,请使用np.histogram函数。它返回一个直方图和箱。因此,您可以存储结果并使用它:

hist, bins = np.histogram(arr, bins=bins, range=range)

如果要绘制结果,可以在应用plt.bar并简单地传递np.histogrambins之后使用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()

输出:

enter image description here enter image description here enter image description here enter image description here

关于浣熊的最终测试:

代码:

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()

输出:

enter image description here