如何从 RGB 通道提取和绘制直方图

问题描述 投票:0回答:1

我正在尝试制作我的图像具有的不同通道的直方图。

没有制作直方图,而是出现错误

"shape mismatch: objects cannot be broadcast to a single shape"

以下是我目前拥有的代码。对我做错了什么有什么想法吗?

使用此示例图像重现错误

import numpy as np
import matplotlib.image as mpimg
import matplotlib.pyplot as plt

im = mpimg.imread('ps09_display-helix.png') 
im = im[100:560, 368:864, :]
pl = np.histogram(im)
plt.bar(range(768), pl[:256], color='r', alpha=0.5)
plt.bar(range(768), pl[256:2*256], color='g', alpha=0.4)
plt.bar(range(768), pl[2*256:], color='b', alpha=0.3)
plt.show()

错误

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-84-e551a5a26f6e> in <module>
      2 im = im[100:560, 368:864, :]
      3 pl = np.histogram(im)
----> 4 plt.bar(range(768), pl[:256], color='r', alpha=0.5)
      5 plt.bar(range(768), pl[256:2*256], color='g', alpha=0.4)
      6 plt.bar(range(768), pl[2*256:], color='b', alpha=0.3)

e:\Anaconda3\lib\site-packages\matplotlib\pyplot.py in bar(x, height, width, bottom, align, data, **kwargs)
   2485         x, height, width=0.8, bottom=None, *, align='center',
   2486         data=None, **kwargs):
-> 2487     return gca().bar(
   2488         x, height, width=width, bottom=bottom, align=align,
   2489         **({"data": data} if data is not None else {}), **kwargs)

e:\Anaconda3\lib\site-packages\matplotlib\__init__.py in inner(ax, data, *args, **kwargs)
   1445     def inner(ax, *args, data=None, **kwargs):
   1446         if data is None:
-> 1447             return func(ax, *map(sanitize_sequence, args), **kwargs)
   1448 
   1449         bound = new_sig.bind(ax, *args, **kwargs)

e:\Anaconda3\lib\site-packages\matplotlib\axes\_axes.py in bar(self, x, height, width, bottom, align, **kwargs)
   2428                 yerr = self._convert_dx(yerr, y0, y, self.convert_yunits)
   2429 
-> 2430         x, height, width, y, linewidth = np.broadcast_arrays(
   2431             # Make args iterable too.
   2432             np.atleast_1d(x), height, width, y, linewidth)

<__array_function__ internals> in broadcast_arrays(*args, **kwargs)

e:\Anaconda3\lib\site-packages\numpy\lib\stride_tricks.py in broadcast_arrays(subok, *args)
    536     args = [np.array(_m, copy=False, subok=subok) for _m in args]
    537 
--> 538     shape = _broadcast_shape(*args)
    539 
    540     if all(array.shape == shape for array in args):

e:\Anaconda3\lib\site-packages\numpy\lib\stride_tricks.py in _broadcast_shape(*args)
    418     # use the old-iterator because np.nditer does not handle size 0 arrays
    419     # consistently
--> 420     b = np.broadcast(*args[:32])
    421     # unfortunately, it cannot handle 32 or more arguments directly
    422     for pos in range(32, len(args), 31):

ValueError: shape mismatch: objects cannot be broadcast to a single shape
python image numpy matplotlib histogram
1个回答
4
投票
  • 随着时间的推移,包的更改导致原始答案不起作用。
    • 代码预计适用于以下软件包版本。答案无法解释未来的软件包更改,并且可能不适用于旧版本的软件包。
    • 如果代码不适用于比下面所述更新的版本,请留下评论。
  • 已在
    python 3.10
    matplotlib 3.5.1
    opencv 4.5.3
    numpy 1.20.3
  • 进行测试

加载图像并提取颜色通道

  • 鉴于下图

    发生
  • ValueError: shape mismatch
    是因为
    image
    中的数组尚未正确提取。
  • 提取 RGB 通道的二维数组
  • 将 RGB 通道的二维数组展平为一维
import matplotlib.pyplot as plt
import numpy as np

# Load the image into an array: image
image = plt.imread('ps09_display-helix.png')

# crop image if necessary - required for the original test image because of wide left/right borders, but new image doesn't have borders
# image = image[100:560, 368:864, :]

# show the cropped image
plt.imshow(image)

# Extract 2-D arrays of the RGB channels: red, green, blue
red, green, blue = image[:,:,0], image[:,:,1], image[:,:,2]

# Flatten the 2-D arrays of the RGB channels into 1-D
red_pixels = red.flatten()
green_pixels = green.flatten()
blue_pixels = blue.flatten()

绘制单个直方图

# Overlay histograms of the pixels of each color in the bottom subplot
plt.figure(figsize=(12, 12))
plt.hist(red_pixels, bins=256, density=False, color='red', alpha=0.5)
plt.hist(green_pixels, bins=256, density=False, color='green', alpha=0.4)
plt.hist(blue_pixels, bins=256, density=False, color='blue', alpha=0.3)

# set labels and ticks
plt.xticks(ticks=np.linspace(0, 1, 17), labels=range(0, 257, 16))

# Cosmetics
plt.title('Histograms from color image')
plt.ylabel('Counts')
plt.xlabel('Intensity')

# Display the plot
plt.show()

替代情节1

  • 每个直方图单独
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(18, 6))
axes = axes.ravel()

for pix, color, ax in zip([red_pixels, green_pixels, blue_pixels], ['red', 'green', 'blue'], axes):

    ax.hist(pix, bins=256, density=False, color=color, alpha=0.5)

    # set labels and ticks
    ax.set_xticks(ticks=np.linspace(0, 1, 17))
    ax.set_xticklabels(labels=range(0, 257, 16), rotation=90)

    # limit the y range if desired
    # ax.set_ylim(0, 10000)

    # set the scale to log
    ax.set_yscale('log')

    # Cosmetics
    ax.set_title(f'Histogram from color {color}')
    ax.set_ylabel('Counts')
    ax.set_xlabel('Intensity')

# Display the plot
plt.tight_layout()
plt.show()

替代情节2

import cv2

color = ('r','g','b')
plt.figure(figsize=(8, 6))
for i, col in enumerate(color):
    histr = cv2.calcHist([image], [i], None, [256], [0, 1])
    plt.plot(histr, color=col)
    plt.xlim([0, 256])

plt.xticks(ticks=range(0, 257, 16), labels=range(0, 257, 16))
plt.yscale('log')
plt.show()

替代情节3

import numpy as np

red_px = np.histogram(red_pixels, bins=256, range=[0, 1])
green_px = np.histogram(green_pixels, bins=256, range=[0, 1])
blue_px = np.histogram(blue_pixels, bins=256, range=[0, 1])

plt.figure(figsize=(8, 6))
plt.plot(red_px[1][:256], red_px[0], color='r')
plt.plot(green_px[1][:256], green_px[0], color='g')
plt.plot(blue_px[1][:256], blue_px[0], color='b')
plt.xticks(ticks=np.linspace(0, 1, 17), labels=range(0, 257, 16))
plt.yscale('log')
plt.show()
  • 替代 2 和 3 如下所示

© www.soinside.com 2019 - 2024. All rights reserved.