首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

opencv进阶学习笔记7:直方图,直方图均衡化,直方图比较,直方图反向投影

  • 23-09-22 21:02
  • 4096
  • 8192
blog.csdn.net

基础版传送门:
python3+opencv学习笔记汇总目录(适合基础入门学习)
进阶版笔记目录链接:
python+opencv进阶版学习笔记目录(适合有一定基础)

直方图基础讲解:
opencv学习笔记21:直方图和掩膜 原理及其应用

图像直方图

numpy实现
函数:hist(数据源,像素级)
数据源:图像,必须是一维数组
像素级:一般是256,指[0-255]
np.raval()可以实现多维数组转一维。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

def plot_demo(image):
    plt.hist(image.ravel(),256,[0,256])
    # plt.hist(image.ravel(),256)#两种写法都对
    plt.show()
print("--------- Hello Python ---------")
src = cv.imread("fangye.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)

plot_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

OpenCV实现

hist=cv2.calcHist(images,channels,mask,histsize,ranges,accumulate)
hist:直方图
images:原始图像,格式[src],需要用中括号括起来
channels:通道,灰色直接[0],BGR对应[0],[1],[2]
mask:掩码图像。如果一个图很大,需要计算部分图的直方图,需要掩码。
histsize:BINS的数量,需要用中括号括起来。一般是[256]
ranges:像素值范围,一般[0,255]
accumulate:累积标识。可选参数、默认false,设为true为计算好几幅图的直方图。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

def image_hist(image):
    color = ('blue', 'green', 'red')
    for i, color in enumerate(color):
        hist = cv.calcHist([image], [i], None, [256], [0, 256])
        plt.plot(hist, color=color)
        plt.xlim([0, 256])
    plt.show()
print("--------- Hello Python ---------")
src = cv.imread("renwu.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)

image_hist(src)
cv.waitKey(0)
cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

图像来源于网图。
图像的主要特征来源于波峰。

图像直方图应用

1全局直方图均衡化
直方图均衡化都是基于灰色图
原理见上面提到的基础链接
效果:使对比图增强

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

def equalHist_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    dst = cv.equalizeHist(gray)
    cv.imshow("equalHist_demo", dst)
print("--------- Hello Python ---------")
src = cv.imread("renwu.jpg")
src=cv.resize(src,None,fx=0.5,fy=0.5)
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)

equalHist_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

2局部直方图均衡化
局部自适应的图像直方图均衡化
自适应直方图均衡化(AHE)是用来提升图像的对比度的一种计算机图像处理技术。和普通的直方图均衡算法不同,AHE算法通过计算图像的局部直方图,然后重新分布亮度来改变图像对比度。因此,该算法更适合于改进图像的局部对比度以及获得更多的图像细节。

不过,AHE有过度放大图像中相同区域的噪音的问题,另外一种自适应的直方图均衡算法即限制对比度直方图均衡(CLAHE)算法能有限的限制这种不利的放大。

cv2.createCLAHE(clipLimit=5.0, tileGridSize=(8, 8))
第一个参数的意义是那一小部分的直方图大于clipLimit的部分将被剪裁掉平均分配 给整个图像;第二个参数的意义是 所分小区域的大小。一般的clipLimit设置的值是40,自定义的话值越大均化的效果越显著,值越接近零,就和原图像没什么区别,
原理图:
在这里插入图片描述

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

def clahe_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    clahe = cv.createCLAHE(clipLimit=3.0, tileGridSize=(5, 5))
    dst = clahe.apply(gray)
    cv.imshow("clahe_demo", dst)
print("--------- Hello Python ---------")
src = cv.imread("renwu1.jpg")
src=cv.resize(src,None,fx=0.6,fy=0.6)
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)

clahe_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

直方图比较

对输入的两张图像计算得到直方图H1与H2,归一化到相同的尺度空间,然后可以通过计算H1与H2的之间的距离得到两个直方图的相似程度进而比较图像本身的相似程度。
直方图比较函数

cv2.compareHist(H1, H2, method)
其中:

H1,H2 分别为要比较图像的直方图
method - 比较方式
比较方式(method)

相关性比较 (method=cv.HISTCMP_CORREL) 值越大,相关度越高,最大值 为1,最小值为0
卡方比较(method=cv.HISTCMP_CHISQR 值越小,相关度越高,最大值无上界,最小值0
巴氏距离比较(method=cv.HISTCMP_BHATTACHARYYA) 值越小,相关度越高,最大值为1,最小值为0

import cv2 as cv
import numpy as np


#rgb直方图
def create_rgb_hist(image):
    h, w, c = image.shape
    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 = np.int(b/bsize)*16*16 + np.int(g/bsize)*16 + np.int(r/bsize)
            rgbHist[np.int(index), 0] = rgbHist[np.int(index), 0] + 1#出现了就加1
    return rgbHist
 #比较函数
def hist_compare(image1, image2):
    hist1 = create_rgb_hist(image1)
    hist2 = create_rgb_hist(image2)
    match1 = cv.compareHist(hist1, hist2, cv.HISTCMP_BHATTACHARYYA)#比较方法1,越小越相似
    match2 = cv.compareHist(hist1, hist2, cv.HISTCMP_CORREL)#相关性越大越相似
    match3 = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR)#卡方越大约不相似
    print("巴氏距离: %s, 相关性: %s, 卡方: %s"%(match1, match2, match3))

print("--------- Hello Python ---------")
src1 = cv.imread("renwu1.jpg")
src2 = cv.imread("renwu.jpg")
src1=cv.resize(src1,None,fx=0.5,fy=0.5)
src2=cv.resize(src2,None,fx=0.5,fy=0.5)
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src1)
cv.imshow("image2", src2)
hist_compare(src1, src2)
cv.waitKey(0)
cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

输入两张完全一样图片
结果

直方图反向投影

直方图反向投影式通过给定的直方图信息,在图像找到相应的像素分布区域,opencv提供两种算法,一个是基于像素的,一个是基于块的。

2D直方图建立
直方图是基于2D的,首先先计算2D直方图建立。

使用函数 cv2.calcHist() 来计算直方图既简单又方便。如果要绘制颜色直方图的话,首先需要将图像的颜色空间从 BGR 转换到 HSV。(记住,计算二维直方图,要从 BGR 转换到 HSV)。计算 2D 直方图,函数的参数要做如下修改:
• channels=[0, 1] 因为我们需要同时处理 H 和 S 两个通道。
• bins=[180, 256]H 通道为 180, S 通道为 256。 如果写其他数值(小于180,256)则表示是通道合并。
• range=[0, 180, 0, 256]H 的取值范围在 0 到 180, S 的取值范围在 0 到 256。
hist = cv2.calcHist([image], [0, 1], None, [32, 32], [0, 180, 0, 256])

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

def hist2d_demo(image):
    hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
    hist = cv.calcHist([image], [0, 1], None, [180, 256], [0, 180, 0, 256])
    #cv.imshow("hist2d", hist)
    plt.imshow(hist, interpolation='nearest')#nearest邻近点插值
    plt.title("2D Histogram")
    plt.show()
print("--------- Hello Python ---------")
src = cv.imread("yangmi.jpg")
src=cv.resize(src,None,fx=0.5,fy=0.5)
#hist2d_demo(src)
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
hist2d_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

直方图反向投影
此段代码有借鉴他人

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


def back_projection_demo():
    # ROI区域
    roi= cv.imread("head.png")
    #roi=cv.resize(roi,None,fx=0.5,fy=0.5)
    #目标搜索区域
    target = cv.imread("renwu.jpg")
    target= cv.resize(target, None, fx=0.2, fy=0.2)
    roi_hsv = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
    target_hsv = cv.cvtColor(target, cv.COLOR_BGR2HSV)

    # show images
    cv.imshow("roi", roi)
    #cv.imshow("target", target)

    roiHist = cv.calcHist([roi_hsv], [0, 1], None, [180,256], [0, 180, 0, 256])#2D直方图
    cv.normalize(roiHist, roiHist, 0, 255, cv.NORM_MINMAX)#归一化到0-255
    dst = cv.calcBackProject([target_hsv], [0, 1], roiHist, [0, 180, 0, 256], 1)
    #cv.imshow("backProjectionDemo", dst)

    # 此处卷积可以把分散的点连在一起
    disc = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
    dst = cv.filter2D(dst, -1, disc)
    # threshold and binary AND
    ret, thresh = cv.threshold(dst, 200, 255, 0)
    # 别忘了是三通道图像,因此这里使用 merge 变成 3 通道
    thresh = cv.merge((thresh, thresh, thresh))
    # 按位操作
    res = cv.bitwise_and(target, thresh)
    res = np.hstack((target, thresh, res))
    cv.imshow('res',res)
    #cv.imwrite('res.jpg', res)

back_projection_demo()
cv.waitKey(0)

cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

原始模板ROI

即从目标图寻找和模板相似的区域(直方图相似)
结果:

要修改 ret, thresh = cv.threshold(dst, 200, 255, 0) 数值才能得到更好。

电气专业的计算机萌新,写博文不容易。如果你觉得本文对你有用,请点个赞再走。谢谢。

文章知识点与官方知识档案匹配,可进一步学习相关知识
OpenCV技能树图像增强和滤波直方图均衡化20473 人正在系统学习中
注:本文转载自blog.csdn.net的总裁余(余登武)的文章"https://blog.csdn.net/kobeyu652453/article/details/107316285"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top