直方图构建图像搜索引擎一

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计算直方图

  1. 读取用于计算直方图的源文件:

    # 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)
    
  2. 灰度直方图计算:

    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)
    

    Python:hist=cv.calcHist(images,channels,mask,histSize,ranges[,hist[,accumulate]]) Python: hist = cv.calcHist( images, channels, mask, histSize, ranges[, hist[, accumulate]] )

  3. 彩色直方图计算:

    # 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)


图像输出

直方图构建图像搜索引擎一