• 本文介绍了python opencv之SURF算法示例，分享给大家，具体如下： 目标： SURF算法基础 opencv总SURF算法的使用 原理： 上节课使用了SIFT算法，当时这种算法效率不高，需要更快速的算法。在06年有人提出了SURF算法...
• ## SURF算法python实现

千次阅读 2019-11-21 20:50:44
SURF算法 ‘’’ import cv2 import numpy as np ‘’‘1、加载图片’’’ img1 = cv2.imread(’./pic/logo1.jpg’,cv2.IMREAD_GRAYSCALE) img1 = cv2.resize(img1,dsize=(600,400)) img2 = cv2.imread(’./pi...

-- coding: utf-8 --
‘’’ SURF算法 ‘’’ import cv2 import numpy as np
‘’‘1、加载图片’’’ img1 = cv2.imread(’./pic/logo1.jpg’,cv2.IMREAD_GRAYSCALE) img1 = cv2.resize(img1,dsize=(600,400)) img2 = cv2.imread(’./pic/logo2.jpg’,cv2.IMREAD_GRAYSCALE) img2 = cv2.resize(img2,dsize=(600,400)) image1 = img1.copy() image2 = img2.copy()
‘’‘2、提取特征点’’’ #创建一个SURF对象 surf = cv2.xfeatures2d.SURF_create(25000) #SIFT对象会使用Hessian算法检测关键点，并且对每个关键点周围的区域计算特征向量。该函数返回关键点的信息和描述符 keypoints1,descriptor1 = surf.detectAndCompute(image1,None) keypoints2,descriptor2 = surf.detectAndCompute(image2,None) print(‘descriptor1:’,descriptor1.shape,‘descriptor2’,descriptor2.shape) #在图像上绘制关键点 image1 = cv2.drawKeypoints(image=image1,keypoints = keypoints1,outImage=image1,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) image2 = cv2.drawKeypoints(image=image2,keypoints = keypoints2,outImage=image2,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) #显示图像 cv2.imshow(‘surf_keypoints1’,image1) cv2.imshow(‘surf_keypoints2’,image2) cv2.waitKey(20)
‘’‘3、特征点匹配’’’ matcher = cv2.FlannBasedMatcher() matchePoints = matcher.match(descriptor1,descriptor2) print(type(matchePoints),len(matchePoints),matchePoints[0])
#提取强匹配特征点 minMatch = 1 maxMatch = 0 for i in range(len(matchePoints)): if minMatch > matchePoints[i].distance: minMatch = matchePoints[i].distance if maxMatch < matchePoints[i].distance: maxMatch = matchePoints[i].distance print(‘最佳匹配值是:’,minMatch) print(‘最差匹配值是:’,maxMatch)
#获取排雷在前边的几个最优匹配结果 goodMatchePoints = [] for i in range(len(matchePoints)): if matchePoints[i].distance < minMatch + (maxMatch-minMatch)/16: goodMatchePoints.append(matchePoints[i])
#绘制最优匹配点 outImg = None outImg = cv2.drawMatches(img1,keypoints1,img2,keypoints2,goodMatchePoints,outImg,matchColor=(0,255,0),flags=cv2.DRAW_MATCHES_FLAGS_DEFAULT) cv2.imshow(‘matche’,outImg) cv2.waitKey(0) cv2.destroyAllWindows()


展开全文
• ## SURF算法源代码

热门讨论 2012-06-19 16:32:22
SURF 算法 识别图片，人脸等高精度识别算法
• python实现特征检测算法SIFT、SURF、ORB等特征检测的算子
• SURF算法吸收了SIFT算法的思想，速度比SIFT快好几倍。下面我会将两个算法整合在一个程序中：import cv2 import numpy as np img = cv2.imread('varese.jpg')#读取要处理的图片 alg = input('Select an A...
SIFT算法是一种与图像比例无关的角点检测算法。
该函数会对不同的图像尺度（尺度不变特征变换）输出相同的结果。
而SURF算法吸收了SIFT算法的思想，速度比SIFT快好几倍。
下面我会将两个算法整合在一个程序中：
import cv2
import numpy as np

alg = input('Select an Alg --> ')

def fd(algorithm):
if algorithm == 'SIFT':
return cv2.xfeatures2d.SIFT_create()
if algorithm == 'SURF':
threshold = input('Enter a threshold --> ')#提示输入SURF算法所采用的阈值
return cv2.xfeatures2d.SURF_create(float(threshold))

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转换为灰度图像
fd_alg = fd(alg)
keypoints,descriptor = fd_alg.detectAndCompute(gray,None)#进行算法的检测和计算

img = cv2.drawKeypoints(image = img,outImage = img,keypoints = keypoints,
flags = cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS,
color = (51,163,236))
cv2.imshow('keypoints',img)
while(True):
if cv2.waitKey(30) & 0xff == ord('q'):
break
cv2.destroyAllWindows()
注意：本次程序中使用了input函数，本人在使用命令行运行该程序时出现报错，而使用默认的sublime运行时是无法进行输入交互的。因此可以通过下载sublimeREPL插件来解决这个问题。
安装插件方法请参考：点击打开链接
原图像：

SIFT处理后：

SURF处理后：

本次SURF处理使用的阈值为8000，阈值越高，能识别的特征就越少。
自己可以采用试探法来得到最优的检测。

我本人也是正在学习opencv，本篇文章仅作为自己学习过程的记录。
如有错漏，请大牛们帮忙指出。一起探讨学习！
展开全文
• SURF算法基础 opencv总SURF算法的使用 原理： 上节课使用了SIFT算法，当时这种算法效率不高，需要更快速的算法。在06年有人提出了SURF算法“加速稳定特征”，从名字上来看，他是SIFT算法的加速版本。 （原文）...
内容来自OpenCV-Python Tutorials 自己翻译整理
目标：
SURF算法基础  opencv总SURF算法的使用
原理：
上节课使用了SIFT算法，当时这种算法效率不高，需要更快速的算法。在06年有人提出了SURF算法“加速稳定特征”，从名字上来看，他是SIFT算法的加速版本。
（原文）  在SIFT算法当中使用高斯差分方程（Difference of Gaussian）对高斯拉普拉斯方程( Laplacian of Gaussian）进行近似。然而，SURF使用盒子滤波器进行近似，下面的图片显示了这种近似的方法。在进行卷积计算的时候可以利用积分图像，这是使用盒子形滤波器的一个优点，即计算某个窗口中的像素和的时候，计算量大小，也就是时间复杂度不受到窗口大小的影响。而且，这种运算可以在不用的尺度空间当中实现。  SURF算法计算关键点的尺度和位置信息使用Hessian矩阵实现。

（解释）  文中的高斯拉普拉斯方程（算子）是检测图像中斑点的一种十分常用的方法。以一维高斯函数来检测一维信号中的斑点为例。有一维信号f，高斯函数的一阶导数

ddxg

d

d

x

g

$\frac{d}{dx}g$，信号与高斯函数的一阶导数卷积后，会在边缘处出现极值。如图：
上面图片是在一维情况下，使用高斯函数的一阶导数的情况，另一种方法是使用高斯函数的二阶导数与信号进行卷积，高斯函数的二阶导数也叫做拉普拉斯变换。  但是，在一维信号斑点检测的实际情况当中，一个斑点可以考虑成是两个相邻的跳突组成，如下图。    类似于在图像当中，一个轮胎可以当成一个斑点，一个苍蝇也可以当成一个斑点。但是在使用高斯函数的二阶导数来检测斑点的时候，使用不同的高斯核（就是方差）运算不同大小的斑点时，计算出来的极值，即响应值会出现衰减。  此时，需要将高斯函数的二阶导数进行正规化，去除方差值不同导致响应值出现的衰减。
以上，是一维高斯函数检测一维信号的原理。二维的图像信号，使用二维高斯函数来检测斑点原理基本相同，此处的二维高斯函数的二阶导数，就叫做高斯拉普拉斯算子也就是LOG，通过改变不同的方差值，可以检测不同尺寸的二维斑点，如图。
文中的高斯差分方程是SIFT算法当中，发明者想要利用两个相邻高斯尺度空间的图像相减来得到一个LOG的近似，因为这样做可以节省时间，而且可以控制精度变化，类似于高等数学当中泰勒公式那玩意-_- 。关于SIFT原理可以看上一篇博客
文中提到的积分图像实际上原理非常简单，类似递推方程。积分图像的目的是想建立一个函数，能够快速得到一个矩形图像区域当中所有像素值的和是多少。那么，设

p(i,j)

p

(

i

,

j

)

$p(i,j)$表示从

(0,0)

(

0

,

0

)

$(0,0)$点到

(i,j)

(

i

,

j

)

$(i,j)$点的所有像素的和是多少，存储在

p(i,j)

p

(

i

,

j

)

$p(i,j)$这个数组里面，如果想要获得W区域的像素和是多少，如图，只要计算

p(i4,j4)−p(i2,j2)−p(i3,j3)+p(i1,j1)

p

(

i

4

,

j

4

)

−

p

(

i

2

,

j

2

)

−

p

(

i

3

,

j

3

)

+

p

(

i

1

,

j

1

)

$p(i_4,j_4)-p(i_2,j_2)-p(i_3,j_3)+p(i_1,j_1)$即可。    如何求得

p(i,j)

p

(

i

,

j

)

$p(i,j)$? 递推公式为，

p(i,j)=p(i−1,j)+p(i,j−1)+I(i,j)−p(i−1,j−1)

p

(

i

,

j

)

=

p

(

i

−

1

,

j

)

+

p

(

i

,

j

−

1

)

+

I

(

i

,

j

)

−

p

(

i

−

1

,

j

−

1

)

$p(i,j)=p(i-1,j)+p(i,j-1)+I(i,j)-p(i-1,j-1)$，这里面

I(i,j)

I

(

i

,

j

)

$I(i,j)$表示像素点

(i,j)

(

i

,

j

)

$(i,j)$处的像素值。
文中提到的Hessian矩阵，学过数学分析、最优化、机器学习之类的人肯定对这玩意非常熟悉，实际上黑塞矩阵就是一个多元函数的二阶偏导数构成的方阵，它的行列式值（Determinant of Hessian )可以反映的局部结构信息,简称DOH。与LOG类似，DOH可以使用不同方差生成高斯函数对各个元的二阶偏导模板，以此来对图像进行卷积运算。 同样，DOH也会在卷积后的函数中，得到对图像信号斑点极值的响应。如图
在SURF算法当中，黑塞矩阵中的L，即为二维高斯函数与图像的卷积，求得黑塞矩阵后，会得到如图。

将上面得到的模板与图像的卷积转换为盒子滤波器，这里使用原文中的图像，如图。

得到三个不同的盒子滤波器以后，对其进行近似和简化操作，并用其表示图像中某点的斑点响应值，遍历图像当中的所有像素，就得到了在某一尺度下斑点检测的响应图像。然后，利用不同的模板尺寸，获取多尺度斑点响应金字塔，在金字塔中搜索极值点，下面的操作就和SIFT算法类似了。

（原文）  为了给找到的特征点赋予方向，以特征点为中心，6s为半径获取水平和垂直小波响应运算结果，这里s是特征点尺度，同时使用高斯加权的方法。然后，他们会被绘制在如下图当中。其中，特征点的主方向估计运算是有一个弧度为60的扇形窗口，在滑动的过程中不断计算其中的响应值之和。有趣的是，小波响应值在任意尺度下使用积分图像很容易被获取。但是在多数情况下，旋转不变性不是必须的，可以代码当中将这一步取消，这样还能够提高算法计算速度，而且在+-15度的情况也保持稳定，此时该方法称作 U-SURF。用户可以设置upright参数，当参数为0计算方向，参数为1不计算方向。
对于特征点描述的建立，SURF再一次使用Haar小波响应，同时使用积分图像使操作变得简单。在一个矩形区域当中，以特征点为中心，划取周围20s×20s区域的大小，以特征点为原点，主方向为横轴，分成四个子区域，每个子区域使用2s的Haar小波响应，对于每个子区域，获取一个向量，记录垂直、水平方向上的小波响应值，如图。    这个特征描述符的长度使64，降低维度可以加速计算，又可以区分特征。为了更好的区分特征点，SURF还使用了长度为128特征描述符。当dy小于0或者大于0时，计算dx或|dx|的和。同样，根据dx的符号计算不同的dy和。因此能够获得双倍的特征。计算复杂度也不会增加。opencv当中的extended参数为0或1时分别对应64和128的特征。  另外一个重要的改善是对潜在的兴趣点使用了拉普拉斯算子符号（黑塞矩阵的迹）。由于之前的计算已经完成对黑塞矩阵的构造，所以这步不会增加复杂度。  拉普拉斯符号在不同明暗背景下区分不同亮度的斑点，在匹配阶段，我们只需要比较拥有相同对比度的特征是否匹配即可，这样加快了计算速度，如图。    SURF算法的速度是SIFT速度的3倍，善于处理模糊和旋转的图像，但是不善于处理视角变化和关照变化。

（解释）  文中的小波响应运算，全称是haar小波运算。这里使用haar小波目的是为了获取图像梯度，使用之前计算好的图像积分结果，这样能够提高计算速度。与SIFT算法类似，在对每个特征点获取主方向时，使用原文中提到的一个π/3大小的扇形窗口，同时以0.2弧度为步长旋转滑动此窗口，在每个窗口当中对的haar响应值的水平方向，垂直方向进行累加。由于时使用一个圆形区域，转换成类似极坐标矢量的方式来表示，每个窗口中的结果

(mw,θw)

(

m

w

,

θ

w

)

$(m_w,\theta_w)$，如图。
主方向最大Haar响应值累加对应的方向。其中，如果除了主方向，还有其它方向的响应累加值较大，算法当中还会额外添加一个特征点，并赋予另外一个次大方向。
文中建立的特征描述符顾名思义，就是描述一个特征点的一组向量，里面唯一确定了一个特征。SURF获取主方向后，需要获取特征点描述子。以特征点为原点，主方向为横轴建立一个二维坐标系，区域大小是20s×20s，分成是个之块，每个子块利用2s的haar模板进行响应计算。然后统计

Σdx、Σ|dx|、Σdy、Σ|dy|

Σ

d

x

、

Σ

|

d

x

|

、

Σ

d

y

、

Σ

|

d

y

|

$\Sigma dx、\Sigma |dx|、\Sigma dy、\Sigma |dy|$，每个20s的窗口分成4×4的子窗口，每个子窗口中又5s×5s个像元。如图    又4×4个子块，每个子块里面记录四个值，所以描述子一共又4×4×4=64个特征。  最后将沿着主方向的小波响应值扭转过来，原理就是简单的旋转矩阵。

代码部分
opencv里面提供的SURF算法和SIFT差不多，这两个玩意都是受到版权保护的，如果你是用pip 一条命令安装的opencv，那么恭喜你用不了SURF和SIFT算法，印象中只有2.4.9版本的opencv库才可以使用。  不过，办法还是有的，再控制台当中输入pip install opencv-contrib-python 就可以用了。  如果还是无法安装，可以直接网站早opencv-contrib-python的轮子，然后放到对应的文件下安装就行了。
我的版本是opencv 3.2，和教程文档中的使用方法不同。  详细参数可以自己去查一查，一查一个准的  https://docs.opencv.org/master/d5/df7/classcv_1_1xfeatures2d_1_1SURF.html
import cv2
import numpy as np

#参数为hessian矩阵的阈值
surf = cv2.xfeatures2d.SURF_create(400)
#找到关键点和描述符
key_query,desc_query = surf.detectAndCompute(img,None)
#把特征点标记到图片上
img=cv2.drawKeypoints(img,key_query,img)

cv2.imshow('sp',img)
cv2.waitKey(0)

凤的嘴上特征点占了这么多，辨识度还是蛮高的~ -_-|||
下面是设置方向，和输出一些值的方法
import cv2
import numpy as np

#参数为hessian矩阵的阈值
surf = cv2.xfeatures2d.SURF_create(4000)

#设置是否要检测方向
surf.setUpright(True)

#输出设置值
print(surf.getUpright())

#找到关键点和描述符
key_query,desc_query = surf.detectAndCompute(img,None)

img=cv2.drawKeypoints(img,key_query,img)

#输出描述符的个数
print(surf.descriptorSize())

cv2.imshow('sp',img)
cv2.waitKey(0)
展开全文
• surf的原始论文。对做图像匹配的朋友有一定帮助。 SURF意指 加速的具有鲁棒性的特征，由Bay在2006年首次提出，这项技术可以应用于计算机视觉的物体识别以及3D重构中。SURF算子由SIFT算子改进而来，一般来说，标准的...
• 1. 遗传算法的科学定义 ​ 遗传算法（Genetic Algorithm, GA）是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型，是一种通过模拟自然进化过程搜索最优解的方法。 ​ 其主要特点是直接对结构...
1. 遗传算法的科学定义
​ 遗传算法（Genetic Algorithm, GA）是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型，是一种通过模拟自然进化过程搜索最优解的方法。
​ 其主要特点是直接对结构对象进行操作，不存在求导和函数连续性的限定；具有内在的隐并行性和更好的全局寻优能力；采用概率化的寻优方法，不需要确定的规则就能自动获取和指导优化的搜索空间，自适应地调整搜索方向。
​ 遗传算法以一种群体中的所有个体为对象，并利用随机化技术指导对一个被编码的参数空间进行高效搜索。其中，选择、交叉和变异构成了遗传算法的遗传操作；参数编码、初始群体的设定、适应度函数的设计、遗传操作设计、控制参数设定五个要素组成了遗传算法的核心内容。
​ 遗传算法起源于对生物系统所进行的计算机模拟研究，它是模仿自然界生物进化机制发展起来的随机全局搜索和优化方法，借鉴了达尔文的进化论和孟德尔的遗传学说，其本质是一种高效、并行、全局搜索的方法，能在搜索过程中自动获取和积累有关搜索空间的知识，并自适应地控制搜索过程以求得最佳解。遗传算法寻优迭代流程如下图所示：

2.进化论知识及遗传算法思想
2.1专业术语
遗传算法 ( GA , Genetic Algorithm ) ，也称进化算法 。 遗传算法是受达尔文的进化论的启发，借鉴生物进化过程而提出的一种启发式搜索算法。因此在介绍遗传算法前有必要简单的介绍生物进化知识，对专业的术语的理解也是必不可少的：
种群 (Population) ：生物的进化以群体的形式进行，这样的一个群体称为种群。
个体(individual)：组成种群的单个生物，算法里指染色体带有特征的实体，也可以理解为染色体。
基因型(genotype)：性状染色体的内部表现；在遗传算法中，由于编码方式不同，进化过程中解的形式和实际问题的形式会有所不同。如原始问题的一个解为

x

i

=

(

−

3

,

2

)

x_i=(-3,2)

，而二进制染色体的形式为

x

i

′

=

00110010100

x_i'=00110010100

(注意这里的二进制编码不是简单地把

x

i

x_i

转化为二进制拼在一起，具体往下看)，即染色体只能由0和1组成，所以需要一个映射函数和反映射函数，使问题的解和染色体表达形式能够进行编码(encoding)和解码(decoding)，即：
encodingdecoding

x

i

′

=

00110010100

x_i'=00110010100

x

i

=

(

−

3

,

2

)

x_i=(-3,2)

=

f

(

x

i

)

f(x_i)

=

f

−

1

(

x

i

)

f^{-1}(x_i)

=

f

(

−

3

,

2

)

f(-3,2)

=

f

−

1

(

00110010100

)

f^{-1}(00110010100)

表现型(phenotype)： 染色体决定的性状的外部表现；在遗传算法中，表现型和基因型是一一对应的，如

x

i

′

=

00110010100

x_i'=00110010100

是基因型，

x

i

=

(

−

3

,

2

)

x_i=(-3,2)

是表现型，表现型是最终实际问题的解的形式。
编码(coding)： DNA中遗传信息在一个长链上按一定的模式排列。遗传编码可看作从表现型到基因型的映射。
解码(decoding)： 基因型到表现型的映射。
进化(evolution)： 种群逐渐适应生存环境，品质不断得到改良。在算法中，进化就是不断的迭代，最终使得目标函数逼近全局最优解。
适应度(fitness)： 度量某个物种对于生存环境的适应程度。在算法中，其实就是计算的目标函数值。
选择(selection)： 以一定的概率从种群中选择若干个个体。一般，选择过程是一种基于适应度的优胜劣汰的过程。一种常用的选择策略是 “比例选择”，也就是个体被选中的概率与其适应度函数值成正比。假设群体的个体总数是M，那么那么一个体Xi被选中的概率为f(Xi)/( f(X1) + f(X2) + ……… + f(Xn) ) 。比例选择实现算法就是所谓的“轮盘赌算法”( Roulette Wheel Selection ) 。
复制(reproduction)： 算法里理解为选择的过程，就是复制父代个体形成子代个体。
交叉(crossover)： 两个染色体的某一相同位置处DNA被切断，前后两串分别交叉组合形成两个新的染色体，即交换部分染色体，也称基因重组或杂交。如下图演示了第3~5个基因随机交换的现象。
**变异(mutation)：**复制时可能（很小的概率）产生某些复制差错，变异产生新的染色体，表现出新的性状。受到环境影响可能会产生变异，在生物种群中，子代个体可能变得更聪明，或者由于变异产生某种遗传病。变异操作是染色体某个位置的随机突变，正常情况下突变概率很小，变异操作如下图所示，第3个和第5个位置的基因发生了突变。

生存竞争，适者生存：对环境适应度高的、牛B的个体参与繁殖的机会比较多，后代就会越来越多。适应度低的个体参与繁殖的机会比较少，后代就会越来越少。
遗传与变异：新个体会遗传父母双方各一部分的基因，同时有一定的概率发生基因变异。
2.2.遗传算法的编码方法
遗传算法常用的编码形式有二进制编码、格雷编码、实数编码、符号编码等。在前面讲解遗传算法基本概念是使用二进制编码为例进行的，由于二进制编码的方案与染色体基因的表现形式最接近、最容易理解，因此下面接着二进制编码的过程。
​ 遗传算法的二进制编码由0和1组成，二进制编码和实数存在一一对应关系，染色体的长度决定

x

i

x_i

的精度。如有一变量

x

∈

[

−

1

,

2

]

x\in [-1,2]

,其精度精确到小数后6位，则相当于将区间

[

−

1

,

2

]

[-1,2]

分成

3

∗

1

0

6

3*10^6

等分，要用二进制表示这个区间范围，需要22位染色体长度，即

2097152

=

2

21

<

3

∗

1

0

6

<

2

22

=

4194304

2097152=2^{21}<3*10^6<2^{22}=4194304

。
​ 如何确定染色体长度？
​ 假设有一决策变量

x

∈

[

a

,

b

]

x\in[a,b]

,精确到小数点c位，用

l

l

位长度的染色体表示，则

0000

⋅

⋅

⋅

000

=

a

=

2

0

−

1

0000···000=a=2^0-1

(

l

l

个0)

111

⋅

⋅

⋅

111

=

b

=

2

m

−

1

111···111=b=2^m-1

(

l

l

个1)
​ 此处假设a=0是为了方便推到公式，这样可以得到编码精度

Δ

x

=

b

−

a

2

m

−

1

\Delta x=\frac{b-a}{2^m-1}

,若精度

Δ

x

=

1

0

c

\Delta x=10^c

,则有

b

−

a

1

0

c

≤

2

m

\frac{b-a}{10^c}\leq 2^m

,由此推出

m

=

l

o

g

2

(

b

−

a

)

+

c

l

o

g

2

10

m=log_2(b-a)+clog_210

.
所以染色体的长度为：

l

=

m

l=m

,当m为整数；

l

=

i

n

t

(

m

)

+

1

l=int(m)+1

,当m不为整数时。
​ 如果有多个决策变量，则将所有的决策变量拼接在一起形成一个整体，相当于矩阵的一行。
​ 得到染色体长度后，如何根据染色体的基因型反向计算表现型的值呢？
​ 染色体是二进制数，而设计的变量是十进制数，这就设计到十进制和二进制的相互转换了。二进制转换十进制的公式如下：

(

b

0

b

1

⋅

⋅

⋅

b

l

)

=

∑

i

=

0

l

2

i

b

i

=

x

t

(b_0b_1···b_l)=\sum_{i=0}^l2^ib_i=x^t

x

=

a

+

x

t

b

−

a

2

l

−

1

x=a+x^t\frac{b-a}{2^l-1}

​ 类似，十进制也可以转二进制，这里就不啰嗦了。
2.3遗传算法的选择操作
​ 遗传算法的选择操作是指选择种群中适应度高的个体形成的子代种群，常用的选择操作有轮盘赌法和精英策略。以下我们以轮盘赌法作为讲解。
​ 其核心思想是不等概率有放回抽样，如下所示，将个体的适应度做归一化计算，归一化值即为个体被选择的概率。
​ 归一化：Xi被选中的概率为P=f(Xi)/( f(X1) + f(X2) + ……… + f(Xn) )
个体适应度归一化适应度被选择概率1250.190.192290.220.223240.180.184120.090.095180.130.136260.190.19

​ 然后进行有放回的抽样，直到抽样规模达到种群的规模时停止，个体被选中的概率由其适应度决定。
​ 在Python中，实现指定概率抽样的代码如下：
import numpy as np
np.random.choice([1,2,3,4,5,6],size=6,p=[0.19,0.22,0.18,0.09,0.13,0.19])

​ 轮盘赌算法的一个简单的实现如下：
轮盘赌算法
def select(X, fitness):
"""根据轮盘赌法选择优秀个体"""
# fitness越小表示越优秀，被选中的概率越大，做 1/fitness 处理
fitness = 1 / fitness
fitness = fitness / fitness.sum()  # 归一化
idx = np.array(list(range(X.shape[0])))
# 根据概率选择
X2_idx = np.random.choice(idx, size=X.shape[0], p=fitness)
X2 = X[X2_idx, :]
return X

3.算法流程
算法的流程如下：
​ Step1:种群初始化:进行随机初始化每个个体的染色体的基因型。
​ Step2:迭代设置:设置迭代次数

g

m

a

x

g_{max}

，令当前迭代次数g=1。
​ Step3:染色体解码，根据染色体的表现型计算个体适应度。
​ Step4:适者生存，只有优秀的个体才能存活，即对个体进行选择操作。
​ Step5:产生下一代个体，即对染色体进行交叉、变异操作。
​ Step6:终止条件判断：判断迭代次数时都达到

g

m

a

x

g_{max}

或误差是否足够小，如果满足则输出染色体的表现型和适应值；否则继续进行跌代，跳转至Step3。
4.代码
4.1 问题
​ 求Rastrigin函数的最小值。
​ Rastrigin函数:

f

(

x

,

y

)

=

2

a

+

x

2

−

a

c

o

s

2

π

x

+

y

2

−

a

c

o

s

2

π

y

f(x,y)=2a+x^2-acos2\pi x+y^2-acos2\pi y

4.2 绘图
画出Rastrigin函数的图像
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

# 生成X和Y的数据
X = np.arange(-5, 5, 0.1)
Y = np.arange(-5, 5, 0.1)
X, Y = np.meshgrid(X, Y)
a = 10
# 目标函数
Z = 2 * a + X ** 2 - a * np.cos(2 * np.pi * X) + Y ** 2 - a * np.cos(2 * np.pi * Y)

# 绘图
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm)
plt.show()


4.3 问题分析
​ 在Rastrigin中有两个变量x和y，取值范围都是[-5,5],

f

(

x

)

f(x)

精度精确到小数点后5位，所以染色体需要40个基因位，前20个基因位表示x的编码，后20个基因位表示变量y的编码。假设种群的规模为50，则种群可表示为50*40的矩阵，矩阵的每一行都是一个个体。
4.4 计算适应度
import numpy as np
import matplotlib.pyplot as plt

def fitness_func(X):
# 目标函数，即适应度值，X是种群的表现型
a = 10
pi = np.pi
x = X[:, 0]
y = X[:, 1]
return 2 * a + x ** 2 - a * np.cos(2 * pi * x) + y ** 2 - a * np.cos(2 * 3.14 * y)


4.5 解码
def decode(x, a, b):
"""解码，即基因型到表现型"""
xt = 0
for i in range(len(x)):
xt = xt + x[i] * np.power(2, i)
return a + xt * (b - a) / (np.power(2, len(x)) - 1)


4.6 编码
def decode_X(X: np.array):
"""对整个种群的基因解码，上面的decode是对某个染色体的某个变量进行解码"""
X2 = np.zeros((X.shape[0], 2))
for i in range(X.shape[0]):
xi = decode(X[i, :20], -5, 5)
yi = decode(X[i, 20:], -5, 5)
X2[i, :] = np.array([xi, yi])
return X2

4.7 适者生存，个体选择
def select(X, fitness):
"""根据轮盘赌法选择优秀个体"""
fitness = 1 / fitness  # fitness越小表示越优秀，被选中的概率越大，做 1/fitness 处理
fitness = fitness / fitness.sum()  # 归一化
idx = np.array(list(range(X.shape[0])))
X2_idx = np.random.choice(idx, size=X.shape[0], p=fitness)  # 根据概率选择
X2 = X[X2_idx, :]
return X2

4.8 产生后代，交叉变异
def crossover(X, c):
"""按顺序选择2个个体以概率c进行交叉操作"""
for i in range(0, X.shape[0], 2):
xa = X[i, :]
xb = X[i + 1, :]
for j in range(X.shape[1]):
# 产生0-1区间的均匀分布随机数，判断是否需要进行交叉替换
if np.random.rand() <= c:
xa[j], xb[j] = xb[j], xa[j]
X[i, :] = xa
X[i + 1, :] = xb
return X

def mutation(X, m):
"""变异操作"""
for i in range(X.shape[0]):
for j in range(X.shape[1]):
if np.random.rand() <= m:
X[i, j] = (X[i, j] + 1) % 2
return X


4.9 主要算法流程


def ga():
"""遗传算法主函数"""
c = 0.3  # 交叉概率
m = 0.05  # 变异概率
best_fitness = []  # 记录每次迭代的效果
best_xy = []
iter_num = 100  # 最大迭代次数
X0 = np.random.randint(0, 2, (50, 40))  # 随机初始化种群，为50*40的0-1矩阵
for i in range(iter_num):
X1 = decode_X(X0)  # 染色体解码
fitness = fitness_func(X1)  # 计算个体适应度
X2 = select(X0, fitness)  # 选择操作
X3 = crossover(X2, c)  # 交叉操作
X4 = mutation(X3, m)  # 变异操作
# 计算一轮迭代的效果
X5 = decode_X(X4)
fitness = fitness_func(X5)
best_fitness.append(fitness.min())
x, y = X5[fitness.argmin()]
best_xy.append((x, y))
X0 = X4
# 多次迭代后的最终效果
print("最优值是：%.5f" % best_fitness[-1])

print("最优解是：x=%.5f, y=%.5f" % best_xy[-1])
# 最优值是：0.00000
# 最优解是：x=0.00000, y=-0.00000
# 打印效果
plt.plot(best_fitness, color='r')
plt.show()

ga()

4.10 求解结果
最优值是：0.00000 最优解是：x=-0.00000, y=0.00000

参考： 苏振裕.《Python最优化实战》[M].北京大学出版社
我的GitHub

展开全文
• 算法简介2.SURF与SIFT的具体差异二、Python代码实践1.测试环境2.测试代码3.核心函数4.测试结果 一、SURF算法 1.算法简介 SURF（Speeded-Up Robust Features）加速稳健特征，是一种稳健的局部特征点检测和描述算法。 ...
• 冲浪算法matlab代码冲浪 提升稀疏和低秩张量回归 arXiv 下载： 我们已经包含了代码的详细注释。 您可以先通过代码生成模拟数据，然后运行我们的 SURF 算法进行训练和测试。 该代码是使用 Tensorlab 工具箱为 MATLAB ...
• 使用SIFT或者SURF特征进行图像匹配，实现语言为python2.7+opencv3.1，代码有注释，有文档说明，并配有测试图像资源
• ## SURF匹配python实现

千次阅读 2019-06-27 14:43:48
# -*- coding: utf-8 -*- """ Created on Thu Jun 20 16:25:27 2019 推荐使用OPENCV 3.1.0及以下版本 两幅png为middlebury上面的示例图片 @author: zhangzhicheng """ import numpy as np import cv2 ...
• 我们在上个教程讨论了SIFT算法用于检测特征点，SIFT算法对旋转、...SURF算法原理 SURF特征检测的步骤 1.尺度空间的极值检测：搜索所有尺度空间上的图像，通过Hessian来识别潜在的对尺度和选择不变的兴趣点。 2.特征
• ## 粒子群算法Python代码实现

千次阅读 热门讨论 2021-08-23 20:43:24
粒子群优化算法起源于对鸟群觅食活动的分析。鸟群在觅食的时候通常会毫无征兆的聚拢，分散，以及改变飞行的轨迹，但是在不同个体之间会十分默契的保持距离。所以粒子群优化算法模拟鸟类觅食的过程，将待求解问题的...
• python使用Opencv的Sift/Surf算法使用python进行图像配准、拼接以及融合时，常用的算法有Sift算子、Surf算子、Harris算子等。由于sift算法的专利问题，部分opencv版本的Sift/Surf算法无法使用，即无法调用cv2....
• python 使用opencv库中的SURF算法 代码踩坑 opencv-python\opencv_contrib\modules\ xfeatures2d\src\surf.cpp:1016: error: (-213:The function/feature is not implemented) Set OPENCV_ENABLE_NONFREE CMake ...
• SURF（加速稳健特征）算法。跟它的名字一样，这是个算法是加速版的 SIFT。 import cv2 import numpy as np img = cv2.imread('image.jpg') gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) surf = cv2.xfeatures2d....
• 利用 SIFT 实现图像拼接：https://goodgoodstudy.blog.csdn.net/article/details/89157849
• SURF算法以及源码分析
• 基于windows7_32位系统和Qt5.5.1+opencv249平台开发的基于SURF算法的图像拼接软件！
• 项目需要SURF算法作为相似度判别时 因SURF中detecetAndCompute阶段时间过长 故先将特征点保存后再使用时直接调用即可 2.代码 # -*- coding: utf-8 -*- """ Created on Mon Jan 14 14:56:27 2019 @...
• Python脚本实现了几种用于图像聚类的算法 1.细节 该存储库包含Python脚本，这些脚本将功能包模型应用于图像聚类。 “特征包”模型是一种将图像表示为代码簿中视觉单词出现的直方图的一种方式，没有空间信息。 首先，...
• 算法可以计算模板和图像之间的相似度，基于SURF特征，可以根据相似度得分来进行模板和图像的匹配。手动指定模板和测试图像就可以运行,语言为python
• 注意： 本章使用的是opencv-contrib-python的3.4.2.16版本，安装过程如下： pip uninstall opencv-python pip install opencv-...0 原理 1OpenCV 中的 SURF 2 举例 0 原理 在上一节中我们学习了使用 SIFT 算...
• 一种基于SURF算法的图像拼接方法本设计涉及一种图像拼接方法，涉及图像处理技术领域。背景技术现有的图像拼接方法一般采用SIFT算法和Harris角点算法，采用SIFT算法和Harris角点算法存在特征点提取速度慢，而且鲁棒性...
• RANSAC算法介绍 定义 RANSAC (RAndom SAmple Consensus,随机采样一致) 算法是从一组含有“外点”(outliers)的数据中正确估计数学模型参数的迭代算法。“外点”一般指的的数据中的噪声，比如说匹配中的误匹配和...
• 基于C++的双摄像头的立体双目测距算法。可以实现对物体目标的捕捉 。
• and Van Gool,L,发表了另一篇论文,“SURF:加速健壮的特征”,引入了一种名为“SURF”的新算法。正如名字所表明的那样,它是一个加速版本的SIFT。 在SIFT中，Lowe用高斯差近似高斯的拉普拉斯算子来寻找尺度空间。SURF...

...

python 订阅