OpenCV实战(1)——图像相似度算法(⽐对像素⽅差,感知哈希算法,模板匹配(OCR数字。。。
如果需要处理的原图及代码,请移步⼩编的GitHub地址
传送门:
如果点击有误:github/LeBron-Jian/ComputerVisionPractice
最近⼀段时间学习并做的都是对图像进⾏处理,其实⾃⼰也是新⼿,各种尝试,所以我这个门外汉想总结⼀下⾃⼰学习的东西,图像处理的流程。但是动起笔来想总结,⼀下却不知道⾃⼰要写什么,那就把⾃⼰做过的相似图⽚搜索的流程整理⼀下,想到什么说什么吧。
⼀:图⽚相似度算法(对像素求⽅差并⽐对)的学习
1.1 算法逻辑
1.1.1 缩放图⽚
将需要处理的图⽚所放到指定尺⼨,缩放后图⽚⼤⼩由图⽚的信息量和复杂度决定。譬如,⼀些简单的图标之类图像包含的信息量少,复杂度低,可以缩放⼩⼀点。风景等复杂场景信息量⼤,复杂度⾼就不能缩放太⼩,容易丢失重要信息。根据⾃⼰需求,弹性的缩放。在效率和准确度之间维持平衡。
1.1.2 灰度处理
通常对⽐图像相似度和颜⾊关系不是很⼤,所以处理为灰度图,减少后期计算的复杂度。如果有特殊需求则保留图像⾊彩。
1.1.3 计算平均值
此处开始,与传统的哈希算法不同:分别依次计算图像每⾏像素点的平均值,记录每⾏像素点的平均值。每⼀个平均值对应着⼀⾏的特征。
1.1.4 计算⽅差
对得到的所有平均值进⾏计算⽅差,得到的⽅差就是图像的特征值。⽅差可以很好的反应每⾏像素特征的波动,既记录了图⽚的主要信息。
1.1.5 ⽐较⽅差
经过上⾯的计算之后,每张图都会⽣成⼀个特征值(⽅差)。到此,⽐较图像相似度就是⽐较图像⽣成⽅差的接近成程度。
⼀组数据⽅差的⼤⼩可以判断稳定性,多组数据⽅差的接近程度可以反应数据波动的接近程度。我们不关注⽅差的⼤⼩,只关注两个⽅差的差值的⼤⼩。⽅差差值越⼩图像越相似!
1.2 代码:
import cv2
import matplotlib.pyplot as plt
#计算⽅差
def getss(list):
#计算平均值
avg=sum(list)/len(list)
#定义⽅差变量ss,初值为0
ss=0
#计算⽅差
for l in list:
ss+=(l-avg)*(l-avg)/len(list)
#返回⽅差
return ss
#获取每⾏像素平均值
def getdiff(img):
#定义边长
Sidelength=30
#缩放图像
size(img,(Sidelength,Sidelength),interpolation=cv2.INTER_CUBIC)
#灰度处理
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#avglist列表保存每⾏像素平均值
avglist=[]
#计算每⾏均值,保存到avglist列表
for i in range(Sidelength):
avg=sum(gray[i])/len(gray[i])
avglist.append(avg)
#返回avglist平均值
return avglist
#读取测试图⽚
img1=cv2.imread("james.jpg")
diff1=getdiff(img1)
print('img1:',getss(diff1))
#读取测试图⽚
img11=cv2.imread("durant.jpg")
diff11=getdiff(img11)
print('img11:',getss(diff11))
ss1=getss(diff1)
ss2=getss(diff11)
print("两张照⽚的⽅差为:%s"%(abs(ss1-ss2))) x=range(30)
plt.figure("avg")
plt.plot(x,diff1,marker="*",label="$jiames$") plt.plot(x,diff11,marker="*",label="$durant$") plt.title("avg")
plt.legend()
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
两张原图:
图像结果如下:
img1: 357.03162469135805
img11: 202.56193703703704
两张照⽚的⽅差为:154.469687654321
实验环境开始设置了图⽚像素值,⽽且进⾏灰度化处理,此⽅法⽐对图像相似对不同的图⽚⽅差很⼤,结果很明显,但是对⽐⽐较相似,特别相似的图⽚不适应。
⼆:图⽚相似度算法(感知哈希算法)的学习
"感知哈希算法"(Perceptual hash algorithm),它的作⽤是对每张图⽚⽣成⼀个"指纹"(fingerprint)字符串,然后⽐较不同图⽚的指纹。结果越接近,就说明图⽚越相似。
2.1 算法步骤
2.1.1 缩⼩尺⼨
将图⽚缩⼩到8x8的尺⼨,总共64个像素。这⼀步的作⽤是去除图⽚的细节,只保留结构、明暗等基本信息,摒弃不同尺⼨、⽐例带来的图⽚差异。
2.1.2 简化⾊彩
将缩⼩后的图⽚,转为64级灰度。也就是说,所有像素点总共只有64种颜⾊。
2.1.3 计算平均值
计算所有64个像素的灰度平均值
2.1.4 ⽐较像素的灰度平均值
将每个像素的灰度,与平均值进⾏⽐较。⼤于或等于平均值,记为1;⼩于平均值,记为0。
2.1.5 计算哈希值
将上⼀步的⽐较结果,组合在⼀起,就构成了⼀个64位的整数,这就是这张图⽚的指纹。组合的次序并不重要,只要保证所有图⽚都采⽤同样次序就⾏了。
得到指纹以后,就可以对⽐不同的图⽚,看看64位中有多少位是不⼀样的。在理论上,这等同于计算(Hamming distance)。如果不相同的数据位不超过5,就说明两张图⽚很相似;如果⼤于10,就说明这是两张不同的图⽚。
此算法参考博客:www.ruanyifeng/blog/2011/07
/principle_of_similar_image_search.html
但是未实现代码,代码如下:
#!/usr/bin/python
import glob
import os
import sys
from PIL import Image
EXTS = 'jpg', 'jpeg', 'JPG', 'JPEG', 'gif', 'GIF', 'png', 'PNG'
def avhash(im):
if not isinstance(im, Image.Image):
im = Image.open(im)
im = im.resize((8, 8), Image.ANTIALIAS).convert('L')
avg = reduce(lambda x, y: x + y, im.getdata()) / 64.
return reduce(lambda x, (y, z): x | (z << y),
enumerate(map(lambda i: 0 if i < avg else 1, im.getdata())),
0)
def hamming(h1, h2):
h, d = 0, h1 ^ h2
while d:
h += 1
d &= d - 1
return h
if __name__ == '__main__':
if len(sys.argv) <= 1 or len(sys.argv) > 3:
print "Usage: %s image.jpg [dir]" % sys.argv[0]
else:
im, wd = sys.argv[1], '.' if len(sys.argv) < 3 else sys.argv[2]
h = avhash(im)
os.chdir(wd)
images = []
for ext in EXTS:
seq = []
prog = int(len(images) > 50 and sys.stdout.isatty())
for f in images:
seq.append((f, hamming(avhash(f), h)))
if prog:
rectangle函数opencvperc = 100. * prog / len(images)
x = int(2 * perc / 5)
print '\ [' + '#' * x + ' ' * (40 - x) + ']',
print '%.2f%%' % perc, '(%d/%d)' % (prog, len(images)),
sys.stdout.flush()
prog += 1
if prog: print
for f, ham in sorted(seq, key=lambda i: i[1]):
print "%d\t%s" % (ham, f)
三:模板匹配
3.1 模板匹配的定义
模板就是⼀幅已知的⼩图像,⽽模板匹配就是在⼀幅⼤图像中搜寻⽬标,已知该图中有要的⽬标,且该⽬标与模板有相同的尺度,⽅
向和图像元素,通过⼀定的算法可以在图像中到⽬标。
模板匹配和卷积原理很像,模板在原图像上开始滑动,计算模板与图像被模板覆盖的地⽅的差别程度,这个差别程度的计算⽅法在opencv⾥有6种,然后将每次计算的结果放⼊⼀个矩阵⾥,作为结果输出。假如原图像是A*B⼤⼩,⽽模板是 a*b⼤⼩,则输出结果的矩阵是(A-a+1)*(B-b+1)。
3.2 模板匹配⽅法
模板匹配在opencv中的函数为 cv2.matchTemplate(),下⾯看⼀下其源码:
def matchTemplate(image, templ, method, result=None, mask=None): # real signature unknown; restored from __doc__
"""
matchTemplate(image, templ, method[, result[, mask]]) -> result
. @brief Compares a template against overlapped image regions.
.
. The function slides through image , compares the overlapped patches of size \f$w \times h\f$ against
. templ using the specified method and stores the comparison results in result . Here are the formulae
. for the available comparison methods ( \f$I\f$ denotes image, \f$T\f$ template, \f$R\f$ result ). The summation
. is done over template and/or the image patch: \f$x' = 0...w-1, y' = 0...h-1\f$
.
. After the function finishes the comparison, the best matches can be found as global minimums (when
. #TM_SQDIFF was used) or maximums (when #TM_CCORR or #TM_CCOEFF was used) using the
. #minMaxLoc function. In case of a color image, template summation in the numerator and each sum in
. the denominator is done over all of the channels and separate mean values are used for each channel.
. That is, the function can take a color template and a color image. The result will still be a
. single-channel image, which is easier to analyze.
.
. @param image Image where the search is running. It must be 8-bit or 32-bit floating-point.
. @param templ Searched template. It must be not greater than the source image and have the same
. data type.
. @param result Map of comparison results. It must be single-channel 32-bit floating-point. If image
. is \f$W \times H\f$ and templ is \f$w \times h\f$ , then result is \f$(W-w+1) \times (H-h+1)\f$ .
. @param method Parameter specifying the comparison method, see #TemplateMatchModes
. @param mask Mask of searched template. It must have the same datatype and size with templ. It is
. not set by default. Currently, only the #TM_SQDIFF and #TM_CCORR_NORMED methods are supported.
"""
pass
下⾯对模板匹配⽅法进⾏解释:
cv2.TM_CCOEFF:系数匹配法,计算相关系数,计算出来的值越⼤,越相关
cv2.TM_CCOEFF_NORMED:相关系数匹配法,计算归⼀化相关系数,计算出来的值越接近1,越相
关
cv2.TM_CCORR:相关匹配法,计算相关性,计算出来的值越⼤,越相关
cv2.TM_CCORR_NORMED:归⼀化相关匹配法,计算归⼀化相关性,计算出来的值越接近1,越相关
cv2.TM_SQDIFF:平⽅差匹配法,计算平⽅不同,计算出来的值越⼩,越相关
cv2.TM_SQDIFF_NORMED:归⼀化平⽅差匹配法,计算归⼀化平⽅不同,计算出来的值越接近0,越相关
公式复制opencv官⽹,如下:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论