histogram
使用np进行直方图像素统计
通过histogram对图像的三个通道分别进行一维直方图统计,由于被统计的数组必须是一维的,所以使用ravel将二维数组转换为一维数组,通过range参数指定统计区间为0--256,bin参数指定将统计区间分为256等分,histogram返回两个数组hist和x,hist为统计结果,长度为bin,而x是统计区间,长度为bin+1,hist[i]的值为数组中满足x[i]<=v
用histogram2d对通道0和通道2进行二维直方图统计,被统计的数组是两个一维数组,因此也需要使用ravel处理,他们分别是图像通道0和通道2的数据,bins和ranges参数都变成了有两个元素的序列,分别与两个数组相对应,返回的统计结果hist2是一个二维数组,其形状由bins决定,第0轴与第一个数组相对应,第1轴与第二个数组相对应,它是由两个一维数组的对应元素所构成的二维矢量的分布统计结果。
统计结果中亮度比较大的 地方表示图像中红色值在150--200和蓝色值在50-100附近的像素比较多
import cv2 as cv
import pylab as pl
import numpy as np
img = cv.imread('lena.jpg')
fig, ax = pl.subplots(1, 2, figsize=(12, 5))
colors = ['blue', 'green', 'red']
for i in range(3):
hist, x = np.histogram(img[:, :, i].ravel(), bins=256, range=(0, 256))
ax[0].plot(0.5 * (x[:-1] + x[1:]), hist, label=colors[i], color=colors[i])
ax[0].legend(loc='upper left')
ax[0].set_xlim(0, 256)
hist2, x2, y2 = np.histogram2d(
img[:, :, 0].ravel(),
img[:, :, 2].ravel(),
bins=(100, 100),
range=[(0, 256), (0, 256)]
)
ax[1].imshow(hist2, extent=(0, 256, 0, 256), origin=('lower'), cmap='gray')
ax[1].set_ylabel('blue')
ax[1].set_xlabel('red')
pl.show()
calcHist
opencv自带的直方图统计函数为calcHist,支持对多副图像进行N维直方图统计,因此第一个参数是图像列表,对img的三个通道(0,1,2)进行三维直方图统计,每个通道的等分数为(30,20,10),所有通道的取值范围都为(0,256),返回结果是一个形状为(30,20,10)的数组
import cv2 as cv
import pylab as pl
import numpy as np
img = cv.imread('lena.jpg')
result = cv.calcHist(
[img],
channels=(0, 1, 2),
mask=None,
histSize=(30, 20, 10),
ranges=(0, 256, 0, 256, 0, 256),
)
# (30, 20, 10)
print(result.shape)
直方图反向映射
计算出直方图后,可以使用calcBackProject将图像中的每个点替换为他在直方图中所对应的值,于是在直方图中出现次数越高,图像中对应的像素就越亮,可以使用这种方法找出图像中和直方图相匹配的区域
在图像中截取需要匹配的部分,计算待匹配部分的直方图,然后应用到目标图片中
局部阈值二值化效果
首先载入图片,转为hsv色系即色相,饱和度,和明度,相对模板图像的色相和饱和度进行二维直方图计算,在色相和饱和度空间进行颜色匹配能够得到比较好的匹配结果,为了后序计算像素值不溢出,进行归一化到0--255范围内
载入目标图像,转到hsv色系,将模板的统计结果匹配到目标图像
二值化处理,可以自己设置阈值,可以使用自适应二值化
形态学处理,开闭和鹏展腐蚀操作,为了更好的找到目标区域,消除杂点
这种方法适用于在视频中跟踪一个颜色鲜明的物体,在跟踪物体之前首先对一幅物体充满整个画面的图像进行直方图统计,然后对视频的帧进行calcBackProject计算
import cv2 as cv
import numpy as np
img = cv.imread('selection2.jpg')
img_hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
cv.imshow('img', img)
cv.imshow('hsv', img_hsv)
result = cv.calcHist(
[img_hsv],
[0, 1],
None,
[40, 40],
[0, 256, 0, 256]
)
result /= np.max(result) / 255
# img2 = cv.imread('orange.jpg')
img2 = cv.imread('fruits.jpg')
cv.imshow('orange', img2)
img_hsv2 = cv.cvtColor(img2, cv.COLOR_BGR2HSV)
cv.imshow('orange hsv', img_hsv2)
img_bp = cv.calcBackProject(
[img_hsv2],
channels=[0, 1],
hist=result,
ranges=[0, 256, 0, 256],
scale=1,
)
# 自定义二值化
# _, img_th = cv.threshold(img_bp, 128, 255, cv.THRESH_BINARY_INV)
# 局部二值化,自适应阈值
# ADAPTIVE_THRESH_GAUSSIAN_C ADAPTIVE_THRESH_MEAN_C
# blockSize 必须为奇数
img_th = cv.adaptiveThreshold(img_bp, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)
cv.imshow('th', img_th)
# 核的大小和形状
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
# 开操作
img_mp = cv.morphologyEx(img_th, cv.MORPH_OPEN, kernel, iterations=5)
cv.imshow('mp', img_mp)
cv.waitKey(0)
转载至链接:https://my.oschina.net/ahaoboy/blog/1933912