OpenCV-Python实战(番外篇)——OpenCV、NumPy和Matplotlib直方图比较

x33g5p2x  于2021-10-01 转载在 Python  
字(4.4k)|赞(0)|评价(0)|浏览(562)

前言

在《OpenCV-Python实战(7)——直方图详解(❤️万字长文,含大量示例❤️)》中,我们学习了使用 OpenCV 提供的 cv2.calcHist() 函数来计算直方图。此外,NumPyMatplotlib 同样也为创建直方图提供了类似的函数。出于提高性能目的,我们来比较这些函数,使用 OpenCVNumPyMatplotlib 创建直方图,然后测量每个直方图计算的执行时间并将结果绘制在图形中。

OpenCV、NumPy和Matplotlib灰度直方图比较

使用 timeit.default_timer 测量执行时间,因为它会自动提供系统平台和 Python 版本上可用的最佳时钟,首先将其导入:

  1. from timeit import default_timer as timer

可以使用以下方法计算程序的执行时间:

  1. start = timer()
  2. # 程序执行
  3. end = timer()
  4. execution_time = start - end

考虑到 default_timer() 测量值可能会受到同时运行的其他程序的影响。因此,获取准确计时的最佳方法是重复数次并使用最佳时间。
而为了计算和比较直方图,我们需要使用以下函数:

  1. OpenCV 提供 cv2.calcHist() 函数
  2. NumPy 提供的 np.histogram() 函数
  3. Matplotlib 提供的 plt.hist() 函数

用于计算上述每个函数的执行时间的代码如下:

  1. import numpy as np
  2. import cv2
  3. from matplotlib import pyplot as plt
  4. from timeit import default_timer as timer
  5. def show_img_with_matplotlib(color_img, title, pos):
  6. img_RGB = color_img[:, :, ::-1]
  7. ax = plt.subplot(1, 4, pos)
  8. plt.imshow(img_RGB)
  9. plt.title(title)
  10. plt.axis('off')
  11. def show_hist_with_matplotlib_gray(hist, title, pos, color):
  12. ax = plt.subplot(1, 4, pos)
  13. plt.title(title)
  14. plt.xlabel("bins")
  15. plt.ylabel("number of pixels")
  16. plt.xlim([0, 256])
  17. plt.plot(hist, color=color)
  18. plt.figure(figsize=(18, 6))
  19. plt.suptitle("Comparing histogram (OpenCV, numpy, matplotlib)", fontsize=14, fontweight='bold')
  20. image = cv2.imread('example.png')
  21. gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  22. # 计算 cv2.calcHist() 执行时间
  23. start = timer()
  24. hist = cv2.calcHist([gray_image], [0], None, [256], [0, 256])
  25. end = timer()
  26. # 乘以1000将单位转换为毫秒
  27. exec_time_calc_hist = (end - start) * 1000
  28. # 计算 np.histogram() 执行时间
  29. start = timer()
  30. hist_np, bin_np = np.histogram(gray_image.ravel(), 256, [0, 256])
  31. end = timer()
  32. exec_time_np_hist = (end - start) * 1000
  33. # 计算 plt.hist() 执行时间
  34. start = timer()
  35. # 调用 plt.hist() 计算直方图
  36. (n, bins, patches) = plt.hist(gray_image.ravel(), 256, [0, 256])
  37. end = timer()
  38. exec_time_plt_hist = (end - start) * 1000
  39. # 绘制灰度图及其直方图
  40. how_img_with_matplotlib(cv2.cvtColor(gray_image, cv2.COLOR_GRAY2BGR), "gray", 1)
  41. show_hist_with_matplotlib_gray(hist, "grayscale histogram (OpenCV)-" + str('% 6.2f ms' % exec_time_calc_hist), 2, 'm')
  42. show_hist_with_matplotlib_gray(hist_np, "grayscale histogram (Numpy)-" + str('% 6.2f ms' % exec_time_np_hist), 3, 'm')
  43. show_hist_with_matplotlib_gray(n, "grayscale histogram (Matplotlib)-" + str('% 6.2f ms' % exec_time_plt_hist), 4, 'm')
  44. plt.show()

OpenCV、NumPy和Matplotlib颜色直方图比较

对比颜色直方图的方法与灰度直方图类似:

  1. import numpy as np
  2. import cv2
  3. from matplotlib import pyplot as plt
  4. from timeit import default_timer as timer
  5. def show_img_with_matplotlib(color_img, title, pos):
  6. img_RGB = color_img[:, :, ::-1]
  7. ax = plt.subplot(1, 4, pos)
  8. plt.imshow(img_RGB)
  9. plt.title(title)
  10. plt.axis('off')
  11. def show_hist_with_matplotlib_rgb(hist, title, pos, color):
  12. ax = plt.subplot(1, 4, pos)
  13. plt.title(title)
  14. plt.xlabel("bins")
  15. plt.ylabel("number of pixels")
  16. plt.xlim([0, 256])
  17. for (h, c) in zip(hist, color):
  18. plt.plot(h, color=c)
  19. plt.figure(figsize=(18, 6))
  20. plt.suptitle("Comparing histogram (OpenCV, numpy, matplotlib)", fontsize=14, fontweight='bold')
  21. image = cv2.imread('example.png')
  22. # 计算 cv2.calcHist() 执行时间
  23. start = timer()
  24. def hist_color_img(img):
  25. histr = []
  26. histr.append(cv2.calcHist([img], [0], None, [256], [0, 256]))
  27. histr.append(cv2.calcHist([img], [1], None, [256], [0, 256]))
  28. histr.append(cv2.calcHist([img], [2], None, [256], [0, 256]))
  29. return histr
  30. hist= hist_color_img(image)
  31. end = timer()
  32. exec_time_calc_hist = (end - start) * 1000
  33. # 计算 np.histogram() 执行时间
  34. start = timer()
  35. def hist_color_img_np(img):
  36. histr = []
  37. hist_np, bin_np = np.histogram(img[:,:,0].ravel(), 256, [0, 256])
  38. histr.append(hist_np)
  39. hist_np, bin_np = np.histogram(img[:,:,1].ravel(), 256, [0, 256])
  40. histr.append(hist_np)
  41. hist_np, bin_np = np.histogram(img[:,:,2].ravel(), 256, [0, 256])
  42. histr.append(hist_np)
  43. return histr
  44. hist_np = hist_color_img_np(image)
  45. end = timer()
  46. exec_time_np_hist = (end - start) * 1000
  47. # 计算 plt.hist 执行时间
  48. start = timer()
  49. def hist_color_img_plt(img):
  50. histr = []
  51. (n, bins, patches) = plt.hist(image[:,:,0].ravel(), 256, [0, 256])
  52. histr.append(n)
  53. (n, bins, patches) = plt.hist(image[:,:,1].ravel(), 256, [0, 256])
  54. histr.append(n)
  55. (n, bins, patches) = plt.hist(image[:,:,2].ravel(), 256, [0, 256])
  56. histr.append(n)
  57. return histr
  58. n = hist_color_img_plt(image)
  59. end = timer()
  60. exec_time_plt_hist = (end - start) * 1000
  61. # 绘制图像及其颜色直方图
  62. show_img_with_matplotlib(image, "color", 1)
  63. show_hist_with_matplotlib_rgb(hist, "color histogram (OpenCV)-" + str('% 6.2f ms' % exec_time_calc_hist), 2, ['b', 'g', 'r'])
  64. show_hist_with_matplotlib_rgb(hist_np, "color histogram (Numpy)-" + str('% 6.2f ms' % exec_time_np_hist), 3, ['b', 'g', 'r'])
  65. show_hist_with_matplotlib_rgb(n, "color histogram (Matplotlib)-" + str('% 6.2f ms' % exec_time_plt_hist), 4, ['b', 'g', 'r'])
  66. plt.show()

由上面两个实例可以看出,cv2.calcHist() 的执行速度比 np.histogram()plt.hist() 都快。因此,出于性能考虑,在计算图像直方图时可以使用 OpenCV 函数。

相关文章