笔记关键词检索?

在所有笔记中搜索你感兴趣的关键词!

《OpenCV3计算机视觉》 ──   Python语言实现(原书第2版)

作者:Joe Minichino&Joseph Howse著 刘波 苗贝贝 史斌 译


python OpenCV 图片相似度 5种算法

5种算法
值哈希算法、差值哈希算法和感知哈希算法都是值越小,相似度越高,取值为0-64,即汉明距离中,64位的hash值有多少不同。 三直方图和单通道直方图的值为0-1,值越大,相似度越高。

import cv2
import numpy as np
from PIL import Image
import requests
from io import BytesIO
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt


def aHash(img):
# 均值哈希算法
# 缩放为8*8
img = cv2.resize(img, (8, 8))
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# s为像素和初值为0,hash_str为hash值初值为''
s = 0
hash_str = ''
# 遍历累加求像素和
for i in range(8):
for j in range(8):
s = s+gray[i, j]
# 求平均灰度
avg = s/64
# 灰度大于平均值为1相反为0生成图片的hash值
for i in range(8):
for j in range(8):
if gray[i, j] > avg:
hash_str = hash_str+'1'
else:
hash_str = hash_str+'0'
return hash_str


def dHash(img):
# 差值哈希算法
# 缩放8*8
img = cv2.resize(img, (9, 8))
# 转换灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
hash_str = ''
# 每行前一个像素大于后一个像素为1,相反为0,生成哈希
for i in range(8):
for j in range(8):
if gray[i, j] > gray[i, j+1]:
hash_str = hash_str+'1'
else:
hash_str = hash_str+'0'
return hash_str


def pHash(img):
# 感知哈希算法
# 缩放32*32
img = cv2.resize(img, (32, 32)) # , interpolation=cv2.INTER_CUBIC

# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 将灰度图转为浮点型,再进行dct变换
dct = cv2.dct(np.float32(gray))
# opencv实现的掩码操作
dct_roi = dct[0:8, 0:8]

hash = []
avreage = np.mean(dct_roi)
for i in range(dct_roi.shape[0]):
for j in range(dct_roi.shape[1]):
if dct_roi[i, j] > avreage:
hash.append(1)
else:
hash.append(0)
return hash


def calculate(image1, image2):
# 灰度直方图算法
# 计算单通道的直方图的相似值
hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])
hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])
# 计算直方图的重合度
degree = 0
for i in range(len(hist1)):
if hist1[i] != hist2[i]:
degree = degree + \
(1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))
else:
degree = degree + 1
degree = degree / len(hist1)
return degree


def classify_hist_with_split(image1, image2, size=(256, 256)):
# RGB每个通道的直方图相似度
# 将图像resize后,分离为RGB三个通道,再计算每个通道的相似值
image1 = cv2.resize(image1, size)
image2 = cv2.resize(image2, size)
sub_image1 = cv2.split(image1)
sub_image2 = cv2.split(image2)
sub_data = 0
for im1, im2 in zip(sub_image1, sub_image2):
sub_data += calculate(im1, im2)
sub_data = sub_data / 3
return sub_data


def cmpHash(hash1, hash2):
# Hash值对比
# 算法中1和0顺序组合起来的即是图片的指纹hash。顺序不固定,但是比较的时候必须是相同的顺序。
# 对比两幅图的指纹,计算汉明距离,即两个64位的hash值有多少是不一样的,不同的位数越小,图片越相似
# 汉明距离:一组二进制数据变成另一组数据所需要的步骤,可以衡量两图的差异,汉明距离越小,则相似度越高。汉明距离为0,即两张图片完全一样
n = 0
# hash长度不同则返回-1代表传参出错
if len(hash1) != len(hash2):
return -1
# 遍历判断
for i in range(len(hash1)):
# 不相等则n计数+1,n最终为相似度
if hash1[i] != hash2[i]:
n = n + 1
return n


def getImageByUrl(url):
# 根据图片url 获取图片对象
html = requests.get(url, verify=False)
image = Image.open(BytesIO(html.content))
return image


def PILImageToCV():
# PIL Image转换成OpenCV格式
path = "/Users/waldenz/Documents/Work/doc/TestImages/t3.png"
img = Image.open(path)
plt.subplot(121)
plt.imshow(img)
print(isinstance(img, np.ndarray))
img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
print(isinstance(img, np.ndarray))
plt.subplot(122)
plt.imshow(img)
plt.show()


def CVImageToPIL():
# OpenCV图片转换为PIL image
path = "/Users/waldenz/Documents/Work/doc/TestImages/t3.png"
img = cv2.imread(path)
# cv2.imshow("OpenCV",img)
plt.subplot(121)
plt.imshow(img)

img2 = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(122)
plt.imshow(img2)
plt.show()

def bytes_to_cvimage(filebytes):
# 图片字节流转换为cv image
image = Image.open(filebytes)
img = cv2.cvtColor(np.asarray(image), cv2.COLOR_RGB2BGR)
return img

def runAllImageSimilaryFun(para1, para2):
# 均值、差值、感知哈希算法三种算法值越小,则越相似,相同图片值为0
# 三直方图算法和单通道的直方图 0-1之间,值越大,越相似。 相同图片为1

# t1,t2 14;19;10; 0.70;0.75
# t1,t3 39 33 18 0.58 0.49
# s1,s2 7 23 11 0.83 0.86 挺相似的图片
# c1,c2 11 29 17 0.30 0.31

if para1.startswith("http"):
# 根据链接下载图片,并转换为opencv格式
img1 = getImageByUrl(para1)
img1 = cv2.cvtColor(np.asarray(img1), cv2.COLOR_RGB2BGR)

img2 = getImageByUrl(para2)
img2 = cv2.cvtColor(np.asarray(img2), cv2.COLOR_RGB2BGR)
else:
# 通过imread方法直接读取物理路径
img1 = cv2.imread(para1)
img2 = cv2.imread(para2)

hash1 = aHash(img1)
hash2 = aHash(img2)
n1 = cmpHash(hash1, hash2)
print('均值哈希算法相似度aHash:', n1)

hash1 = dHash(img1)
hash2 = dHash(img2)
n2 = cmpHash(hash1, hash2)
print('差值哈希算法相似度dHash:', n2)

hash1 = pHash(img1)
hash2 = pHash(img2)
n3 = cmpHash(hash1, hash2)
print('感知哈希算法相似度pHash:', n3)

n4 = classify_hist_with_split(img1, img2)
print('三直方图算法相似度:', n4)

n5 = calculate(img1, img2)
print("单通道的直方图", n5)
print("%d %d %d %.2f %.2f " % (n1, n2, n3, round(n4[0], 2), n5[0]))
print("%.2f %.2f %.2f %.2f %.2f " % (1-float(n1/64), 1 -
float(n2/64), 1-float(n3/64), round(n4[0], 2), n5[0]))

plt.subplot(121)
plt.imshow(Image.fromarray(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)))
plt.subplot(122)
plt.imshow(Image.fromarray(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)))
plt.show()

if __name__ == "__main__":
p1="https://ww3.sinaimg.cn/bmiddle/007INInDly1g336j2zziwj30su0g848w.jpg"
p2="https://ww2.sinaimg.cn/bmiddle/007INInDly1g336j10d32j30vd0hnam6.jpg"
runAllImageSimilaryFun(p1,p2)
 

............

Python&OpenCV轮廓检测及cv2.threshold,cv2.findContours,cv2.cvtColor,cv2.drawContours函数

对与轮廓检测就是cv2.threshold,cv2.findContours,cv2.cvtColor,cv2.drawContours这几个函数的调用。下面就是代码及对这几个函数的解释:

import cv2
import numpy as np
img = np.zeros((200,200),dtype = np.uint8 )#构造一个两百行两两百列的矩阵
img[50:150,50:150]= 225 #把50到150行和50到150列赋值为225
# cv2.imshow('img',img)
# cv2.waitKey()
ret ,thresh = cv2.threshold('img',127,255,0)#选取一个全局阈值,然后就把整幅图像分成了非黑即白的二值图像
'''
cv2.threshold() 函数解释
这个函数有四个参数,第一个原图像,第二个进行分类的阈值,第三个是高于(低于)阈值时赋予的新值,第四个是一个方法选择参数,常用的有:
• cv2.THRESH_BINARY(黑白二值)
• cv2.THRESH_BINARY_INV(黑白二值反转)
• cv2.THRESH_TRUNC (得到的图像为多像素值)
• cv2.THRESH_TOZERO
• cv2.THRESH_TOZERO_INV
该函数有两个返回值,第一个retVal(得到的阈值值(在后面一个方法中会用到)),第二个就是阈值化后的图像。
'''
image,contours ,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
'''
cv2.threshold函数的解释
参数
第一个参数是寻找轮廓的图像;
第二个参数表示轮廓的检索模式,有四种(本文介绍的都是新的cv2接口):
cv2.RETR_EXTERNAL表示只检测外轮廓
cv2.RETR_LIST检测的轮廓不建立等级关系
cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
cv2.RETR_TREE建立一个等级树结构的轮廓。
第三个参数method为轮廓的近似办法
cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
返回值
cv2.findContours()函数返回两个值,一个是轮廓本身,还有一个是每条轮廓对应的属性。'''
color =cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)#将灰度图像转化成BGR图像
'''
cvCvtColor(...),是Opencv里的颜色空间转换函数,可以实现RGB颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像。
参数CV_RGB2GRAY是RGB到gray。
参数 CV_GRAY2RGB是gray到RGB。
'''
img = cv2.drawContours(color,contours,-1,(0,255,0),2)#主要用于画出图像的轮廓
'''
cv2.drawContours的参数解释(此例只用了前五个)
其中第一个参数image表示目标图像,
第二个参数contours表示输入的轮廓组,每一组轮廓由点vector构成,
第三个参数contourIdx指明画第几个轮廓,如果该参数为负值,则画全部轮廓,
第四个参数color为轮廓的颜色,
第五个参数thickness为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部,
第六个参数lineType为线型,
第七个参数为轮廓结构信息,
第八个参数为maxLevel
'''
cv2.imshow('contours',color)
cv2.waitKey()
cv2.destroyAllWindows()
 

............

cv2.applyColorMap

............

提取图片中的指定颜色

............

cv2.bitwise_and

............

HSV

HSV

HSV颜色模型:HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。
这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。
颜色模型编辑

色调H
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,紫色为300°;
饱和度S
饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
明度V
明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
RGB和CMY颜色模型都是面向硬件的,而HSV(Hue Saturation Value)颜色模型是面向用户的。
HSV模型的三维表示从RGB立方体演化而来。设想从RGB沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。

............

CV.ml 机器学习算法

............

反向传播

............

cv2.getStructuringElement

............

cv2.xfeatures2d.SURF_create

............

cv2.resize

............

sklearn.make_classification

make_classification(n_samples=100, n_features=20, n_informative=2, n_redundant=2, n_repeated=0, n_classes=2, n_clusters_per_class=2, weights=None, flip_y=0.01, class_sep=1.0, hypercube=True, shift=0.0, scale=1.0, shuffle=True, random_state=None): 
参数: 

n_features :特征个数= n_informative() + n_redundant + n_repeated 

n_informative:多信息特征的个数 

n_redundant:冗余信息,informative特征的随机线性组合 

n_repeated :重复信息,随机提取n_informative和n_redundant 特征 

n_classes:分类类别 

n_clusters_per_class :某一个类别是由几个cluster构成的 

weights:列表类型,权重比 

class_sep:乘以超立方体大小的因子。 较大的值分散了簇/类,并使分类任务更容易。默认为1 

random_state: 如果是int,random_state是随机数发生器使用的种子; 如果RandomState实例,random_state是随机数生成器; 如果没有,则随机数生成器是np.random使用的RandomState实例。
返回值: 

X:形状数组[n_samples,n_features] 生成的样本。 

y:形状数组[n_samples] 每个样本的类成员的整数标签。

............

cv2.drawKeypoints

drawKeypoints(image, keypoints, outImage, color=None, flags=None) 

image:也就是原始图片 

keypoints:从原图中获得的关键点,这也是画图时所用到的数据 

outputimage:输出 color:颜色设置,通过修改(b,g,r)的值,更改画笔的颜色,b=蓝色,g=绿色,r=红色。 

flags:绘图功能的标识设置flags的四个参数: 

    cv2.DRAW_MATCHES_FLAGS_DEFAULT:创建输出图像矩阵,使用现存的输出图像绘制匹配对和特征点,对每一个关键点只绘制中间点 

    cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG:不创建输出图像矩阵,而是在输出图像上绘制匹配对 

    cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS:对每一个特征点绘制带大小和方向的关键点图形 

    cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS:单点的特征点不被绘制 

............

cv2.FlannBasedMatcher

FLANN英文全称Fast Libary for Approximate Nearest Neighbors,FLANN是一个执行最近邻搜索的库,官方网站http://www.cs.ubc.ca/research/flann。

它包含一组算法,这些算法针对大型数据集中的快速最近邻搜索和高维特征进行了优化,对于大型数据集,它比BFMatcher工作得更快。经验证、FLANN比其他的最近邻搜索软件快10倍。 

flann = cv2.FlannBasedMatcher(indexParams,searchParams) 

其中FLANN匹配对象接收两个参数:indexParams和searchParams。这两个参数在python中以字典形式进行参数传递(在C++中以结构体形式进行参数传递),为了计算匹配,FALNN内部会决定如何处理索引和搜索对象。 

1、indexParams 对于像SIFT,SURF等算法,您可以传递以下内容: indexParams = dict(algorithm = FLANN_INDEX_KDTREE,trees = 5) 参数algorithm用来指定匹配所使用的算法,可以选择的有LinearIndex、KTreeIndex、KMeansIndex、CompositeIndex和AutotuneIndex,这里选择的是KTreeIndex(使用kd树实现最近邻搜索)。KTreeIndex配置索引很简单(只需要指定待处理核密度树的数量,最理想的数量在1~16之间),并且KTreeIndex非常灵活(kd-trees可被并行处理)。 

2、searchParams SearchParams它指定索引数倍遍历的次数。 值越高,精度越高,但也需要更多时间。 如果要更改该值,请传递:searchParams = dict(checks = 50) 实际上、匹配效果很大程度上取决于输入。5 kd-trees和50 checks总能取得具有合理精度的结果,而且能够在很短的时间内完成匹配。

............

生成器

............

SURF(Speeded-Up Robust Features)

SURF算法采用快速Hessian算法检测关键点,而SURF算子会通过一个特征向量来描述关键点周围区域的情况。这和SIFT算法很像,SIFT算法分别采用DoG和SIFT算子来检测关键点和提取关键点的描述符。
SURF特征检测的步骤:
1.尺度空间的极值检测:搜索所有尺度空间上的图像,通过Hessian来识别潜在的对尺度和选择不变的兴趣点。
2.特征点过滤并进行精确定位。
3.特征方向赋值:统计特征点圆形邻域内的Harr小波特征。即在60度扇形内,每次将60度扇形区域旋转0.2弧度进行统计,将值最大的那个扇形的方向作为该特征点的主方向。
4.特征点描述:沿着特征点主方向周围的邻域内,取4×4个矩形小区域,统计每个小区域的Haar特征,然后每个区域得到一个4维的特征向量。一个特征点共有64维的特征向量作为SURF特征的描述子。

............

支持向量机-SVM

............

方向梯度直方图-HOG

............