直方图构建图像搜索引擎一
Clever Girl: A Guide to Utilizing Color Histograms for Computer Vision and Image Search Engines(直方图构建图像搜索引擎一)
英文原文
translator : aaron-clark-aic
图像搜索引擎原理
两图相似可以认为是两图的色彩相似,直方图就是图形色彩的统计。在彩色直方图的相似比较上可以使用距离矩阵(Euclidean欧氏距离, correlation相关系数, Chi-squared卡方分布, intersection交集, Bhattacharyya巴氏距离),下文的相似性使用卡方分布计算。
使用opencv计算直方图
-
读取用于计算直方图的源文件:
# import the necessary packages from matplotlib import pyplot as plt import cv2 as cv # load the image and show it image = cv.imread(".././img/grant.jpg") cv.imshow("image", image) # convert the image to grayscale and create a histogram gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) cv.imshow("gray", gray)
-
灰度直方图计算:
hist = cv.calcHist([gray], [0], None, [255], [0, 255]) plt.figure() plt.title("Grayscale Histogram") plt.xlabel("Bins") plt.ylabel("# of Pixels") plt.plot(hist)
-
彩色直方图计算:
# grab the image channels, initialize the tuple of colors, # the figure and the flattened feature vector chans = cv.split(image) colors = ("b", "g", "r") plt.figure() plt.title("'Flattened' Color Histogram") plt.xlabel("Bins") plt.ylabel("# of Pixels") # loop over the image channels for (chan, color) in zip(chans, colors): # create a histogram for the current channel and # concatenate the resulting histograms for each # channel hist = cv.calcHist([chan], [0], None, [255], [0, 255]) # plot the histogram plt.plot(hist, color = color) plt.xlim([0, 255])
>>>a = [1,2,3] >>> b = [4,5,6] >>> c = [4,5,6,7,8] >>> zipped = zip(a,b) # 打包为元组的列表 [(1, 4), (2, 5), (3, 6)] >>> zip(a,c) # 元素个数与最短的列表一致 [(1, 4), (2, 5), (3, 6)] >>> zip(*zipped) # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式 [(1, 2, 3), (4, 5, 6)]
# 通道分离 (B, G, R) = cv.split(image)
多维直方图
上面的例子中都是基于一个色彩通道的直方图(彩色直方图也是基于一个通道的统计,只是三个通道一起显示),使用多维直方图可以同时统计两个通道的色彩分布。下面的代码建立一个2D的直方图:
# here we are simply showing the dimensionality of the
# flattened color histogram 256 bins for each channel
# x 3 channels = 768 total values -- in practice, we would
# normally not use 256 bins for each channel, a choice
# between 32-96 bins are normally used, but this tends
# to be application dependent
# let's move on to 2D histograms -- I am reducing the
# number of bins in the histogram from 256 to 32 so we
# can better visualize the results
fig = plt.figure()
# plot a 2D color histogram for green and blue
ax = fig.add_subplot(311)
hist = cv.calcHist([chans[1], chans[0]], [0, 1], None,
[32, 32], [0, 255, 0, 255])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for Green and Blue")
plt.colorbar(p)
# plot a 2D color histogram for green and red
ax = fig.add_subplot(312)
hist = cv.calcHist([chans[1], chans[2]], [0, 1], None,
[32, 32], [0, 255, 0, 255])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for Green and Red")
plt.colorbar(p)
# plot a 2D color histogram for blue and red
ax = fig.add_subplot(313)
hist = cv.calcHist([chans[0], chans[2]], [0, 1], None,
[32, 32], [0, 255, 0, 255])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for Blue and Red")
plt.colorbar(p)
# finally, let's examine the dimensionality of one of
# the 2D histograms
三维直方图
没有找到比较好可以直接显示3D的方式,只能是说hist中的数据是对的。
# our 2D histogram could only take into account 2 out
# of the 3 channels in the image so now let's build a
# 3D color histogram (utilizing all channels) with 8 bins
# in each direction -- we can't plot the 3D histogram, but
# the theory is exactly like that of a 2D histogram, so
# we'll just show the shape of the histogram
hist3 = cv.calcHist([chans[0], chans[1], chans[2]], [0, 1, 2],
None, [32, 32, 32], [0, 255, 0, 255, 0, 255])
本节全部代码
# import the necessary packages
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import cv2 as cv
# load the image and show it
image = cv.imread(".././img/grant.jpg")
cv.imshow("image", image)
# convert the image to grayscale and create a histogram
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("gray", gray)
hist = cv.calcHist([gray], [0], None, [255], [0, 255])
plt.figure()
plt.title("Grayscale Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
plt.plot(hist)
plt.xlim([0, 255])
# grab the image channels, initialize the tuple of colors,
# the figure and the flattened feature vector
chans = cv.split(image)
colors = ("b", "g", "r")
plt.figure()
plt.title("'Flattened' Color Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
# loop over the image channels
for (chan, color) in zip(chans, colors):
# create a histogram for the current channel and
# concatenate the resulting histograms for each
# channel
hist = cv.calcHist([chan], [0], None, [255], [0, 255])
# plot the histogram
plt.plot(hist, color = color)
# here we are simply showing the dimensionality of the
# flattened color histogram 256 bins for each channel
# x 3 channels = 768 total values -- in practice, we would
# normally not use 256 bins for each channel, a choice
# between 32-96 bins are normally used, but this tends
# to be application dependent
# let's move on to 2D histograms -- I am reducing the
# number of bins in the histogram from 256 to 32 so we
# can better visualize the results
fig = plt.figure()
# plot a 2D color histogram for green and blue
ax = fig.add_subplot(311)
hist = cv.calcHist([chans[1], chans[0]], [0, 1], None,
[32, 32], [0, 255, 0, 255])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for Green and Blue")
plt.colorbar(p)
# plot a 2D color histogram for green and red
ax = fig.add_subplot(312)
hist = cv.calcHist([chans[1], chans[2]], [0, 1], None,
[32, 32], [0, 255, 0, 255])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for Green and Red")
plt.colorbar(p)
# plot a 2D color histogram for blue and red
ax = fig.add_subplot(313)
hist = cv.calcHist([chans[0], chans[2]], [0, 1], None,
[32, 32], [0, 255, 0, 255])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for Blue and Red")
plt.colorbar(p)
# finally, let's examine the dimensionality of one of
# the 2D histograms
# our 2D histogram could only take into account 2 out
# of the 3 channels in the image so now let's build a
# 3D color histogram (utilizing all channels) with 8 bins
# in each direction -- we can't plot the 3D histogram, but
# the theory is exactly like that of a 2D histogram, so
# we'll just show the shape of the histogram
hist3 = cv.calcHist([chans[0], chans[1], chans[2]], [0, 1, 2],
None, [32, 32, 32], [0, 255, 0, 255, 0, 255])
plt.show()
cv.waitKey(0)