写点什么

Python OpenCV 图像处理之直方图的应用,取经之旅第 26 天

发布于: 2021 年 04 月 15 日
Python OpenCV 图像处理之直方图的应用,取经之旅第 26 天

Python OpenCV 365 天学习计划,与橡皮擦一起进入图像领域吧。


基础知识铺垫

上篇博客 Python OpenCV 图像处理之图像直方图,取经之旅第 25 天中,我们重点学习了直方图的绘制方法与应用,本篇博客继续对直方图进行分析。


本篇博客咱们首先学习一下,如何用直方图去比较两幅图片的相似性。


通过 <kbd>cv2.compareHist</kbd> 函数计算图片的相似度,在今天的学习中,橡皮擦并没有 get 到一个特别好的场景,故本部分从语法角度进行学习。

cv2.compareHist 函数

该函数原型如下:


cv2.compareHist(H1, H2, method)
复制代码


参数说明如下:


  1. H1,H2:要比较图像的直方图;

  2. method: 比较方式


其中比较方式涉及如下几种枚举值。


  • <kbd>cv2.HISTCMP_CORREL</kbd>:相关性比较,值越大,相关度越高,最大值为 1,最小值为 0;

  • <kbd>cv2.HISTCMP_CHISQR</kbd>:卡方比较,值越小,相关度越高,最大值无上界,最小值 0;

  • <kbd>cv2.HISTCMP_BHATTACHARYYA</kbd>:巴氏距离比较,值越小,相关度越高,最大值为 1,最小值为 0;

  • <kbd>cv2.HISTCMP_INTERSECT</kbd>:十字交叉,值越大越相似。


先比较灰度图的,运行下述代码即可。


import cv2 as cvimport numpy as npfrom matplotlib import pyplot as plt

def create_gray_hist(image): # 创建一个灰度直方图 img = cv.cvtColor(image, cv.COLOR_BGR2GRAY) hist = cv.calcHist([img], [0], None, [256], [0, 256]) return hist

def hist_compare(image1, image2):
# 第一幅图的灰度图直方图 hist1 = create_gray_hist(image1) # 第二幅图的灰度图直方图 hist2 = create_gray_hist(image2) # 进行三种方式的直方图比较 match1 = cv.compareHist(hist1, hist2, cv.HISTCMP_BHATTACHARYYA) match2 = cv.compareHist(hist1, hist2, cv.HISTCMP_CORREL) match3 = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR) match4 = cv.compareHist(hist1, hist2, cv.HISTCMP_INTERSECT) print("巴氏距离:%s, 相关性:%s, 卡方:%s, 十字交叉:%s" % (match1, match2, match3, match4))

src1 = cv.imread("./black.jpg")cv.imshow("diff1", src1)src2 = cv.imread("./yellow.jpg")cv.imshow("diff2", src2)
plt.subplot(1, 2, 1)plt.title("diff1")plt.plot(create_gray_hist(src1))plt.subplot(1, 2, 2)plt.title("diff2")plt.plot(create_gray_hist(src2))
hist_compare(src1, src2)plt.show()while True: k = cv.waitKey(0) & 0xFF if k == 27: breakcv.destroyAllWindows()
复制代码


结果如下图所示,这里我找的是两个相似的图片(从找不同游戏里面找到的)。



得到的结果如下:


巴氏距离:0.0501735845451386, 相关性:0.9855477082033252, 卡方:3887.8752812639, 十字交叉:166493.0
复制代码


由于两张图非常相似,得到的结果也符合刚才的说明。


  • 巴氏距离:0.0501735845451386 >>> 值越小,相关度越高,最大值为 1,最小值为 0;

  • 相关性:0.9855477082033252 >>> 值越大,相关度越高,最大值为 1,最小值为 0;

  • 卡方:3887.8752812639 >>> 值越小,相关度越高,最大值无上界,最小值 0;(不过看起来,这个好像用处不大)

  • 十字交叉:166493.0 >>> 十字交叉,值越大越相似。


切换成不同的两张图片,可以看一下运行结果,首先看灰度直方图。



在看得到的各个值:


巴氏距离:0.28273836677812036, 相关性:0.4615912771396342, 卡方:186501.9955618743, 十字交叉:126877.0
复制代码


接下来,我们比较一下彩色图的直方图,这部分我也在网上看到了一个算法,但是由于代码实在没看太懂,直接忽略掉了。以下代码转载自网络,建议本阶段,看一下就好,不要钻牛角尖。


代码来源:网络。


def create_rgb_hist(image):  """"创建 RGB 三通道直方图(直方图矩阵)"""    h, w, c = image.shape    # 创建一个(16*16*16,1)的初始矩阵,作为直方图矩阵    # 16*16*16的意思为三通道每通道有16个bins    rgbhist = np.zeros([16 * 16 * 16, 1], np.float32)    bsize = 256 / 16    for row in range(h):        for col in range(w):            b = image[row, col, 0]            g = image[row, col, 1]            r = image[row, col, 2]            # 人为构建直方图矩阵的索引,该索引是通过每一个像素点的三通道值进行构建            index = int(b / bsize) * 16 * 16 + int(g / bsize) * 16 + int(r / bsize)             # 该处形成的矩阵即为直方图矩阵            rgbhist[int(index), 0] += 1    plt.ylim([0, 10000])    plt.grid(color='r', linestyle='--', linewidth=0.5, alpha=0.3)    return rgbhist
复制代码


不过,除了灰度直方图,咱们用已有的知识可以比较不同通道的直方图。


具体代码修改部分如下:


def create_gray_hist(image):    # 创建一个灰度直方图    # img = cv.cvtColor(image, cv.COLOR_BGR2GRAY)    hist = cv.calcHist([image], [1], None, [256],  [0, 256])    return hist
复制代码


关于上文提及的 巴氏距离卡方 都属于统计学知识,暂时按下不表。

橡皮擦的小节

希望今天的一个小时,你有所收获,我们下篇博客见~


相关阅读




  1. Python 爬虫 100 例教程,超棒的爬虫教程,立即订阅吧

  2. Python 爬虫小课,精彩 9 讲




今天是持续写作的第 <font color="red">66</font> / 100 天。如果你有想要交流的想法、技术,欢迎在评论区留言。




如果你想跟博主建立亲密关系,可以关注同名公众号 <font color="red">梦想橡皮擦</font>,近距离接触一个逗趣的互联网高级网虫。博主 ID:梦想橡皮擦,希望大家<font color="red">点赞</font>、<font color="red">评论</font>、<font color="red">收藏</font>。

发布于: 2021 年 04 月 15 日阅读数: 32
用户头像

爬虫 100 例作者,蓝桥签约作者,博客专家 2021.02.06 加入

6 年产品经理+教学经验,3 年互联网项目管理经验; 互联网资深爱好者; 沉迷各种技术无法自拔,导致年龄被困在 25 岁; CSDN 爬虫 100 例作者。 个人公众号“梦想橡皮擦”。

评论

发布
暂无评论
Python OpenCV 图像处理之直方图的应用,取经之旅第 26 天