Python使用Opencv实现图像特征检测与匹配的方法


Posted in Python onOctober 30, 2019

特征检测是计算机对一张图像中最为明显的特征进行识别检测并将其勾画出来。大多数特征检测都会涉及图像的角点、边和斑点的识别、或者是物体的对称轴。

角点检测 是由Opencv的cornerHarris函数实现,其他函数参数说明如下:

cv2.cornerHarris(src=gray, blockSize=9, ksize=23, k=0.04)
# cornerHarris参数:
# src - 数据类型为 float32 的输入图像。
# blockSize - 角点检测中要考虑的领域大小。
# ksize - Sobel 求导中使用的窗口大小
# k - Harris 角点检测方程中的自由参数,取值参数为 [0,04,0.06].

以国际象棋为例,这是计算机视觉最为常见的分析对象,如图所示:

Python使用Opencv实现图像特征检测与匹配的方法

角点检测代码如下:

import cv2
import numpy as np

img = cv2.imread('chess_board.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# cornerHarris函数图像格式为 float32 ,因此需要将图像转换 float32 类型
gray = np.float32(gray)
# cornerHarris参数:
# src - 数据类型为 float32 的输入图像。
# blockSize - 角点检测中要考虑的领域大小。
# ksize - Sobel 求导中使用的窗口大小
# k - Harris 角点检测方程中的自由参数,取值参数为 [0,04,0.06].
dst = cv2.cornerHarris(src=gray, blockSize=9, ksize=23, k=0.04)
# 变量a的阈值为0.01 * dst.max(),如果dst的图像值大于阈值,那么该图像的像素点设为True,否则为False
# 将图片每个像素点根据变量a的True和False进行赋值处理,赋值处理是将图像角点勾画出来
a = dst>0.01 * dst.max()
img[a] = [0, 0, 255]
# 显示图像
while (True):
 cv2.imshow('corners', img)
 if cv2.waitKey(120) & 0xff == ord("q"):
  break
 cv2.destroyAllWindows()

运行代码,结果如图所示:

Python使用Opencv实现图像特征检测与匹配的方法

但有时候,图像的像素大小对角点存在一定的影响。比如图像越小,角点看上去趋向近似一条直线,这样很容易造成角点的丢失。如果按照上述的检测方法,会造成角点检测结果不相符,因此引入DoG和SIFT算法进行检测Opencv的SIFT类是DoG和SIFT算法组合。

DoG是对同一图像使用不同高斯滤波器所得的结果。

SIFT是通过一个特征向量来描述关键点周围区域的情况。

我们以下图为例:

Python使用Opencv实现图像特征检测与匹配的方法

import cv2
# 读取图片并灰度处理
imgpath = 'varese.jpg'
img = cv2.imread(imgpath)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建SIFT对象
sift = cv2.xfeatures2d.SIFT_create()
# 将图片进行SURF计算,并找出角点keypoints,keypoints是检测关键点
# descriptor是描述符,这是图像一种表示方式,可以比较两个图像的关键点描述符,可作为特征匹配的一种方法。
keypoints, descriptor = sift.detectAndCompute(gray, None)

# cv2.drawKeypoints() 函数主要包含五个参数:
# image: 原始图片
# keypoints:从原图中获得的关键点,这也是画图时所用到的数据
# outputimage:输出
# color:颜色设置,通过修改(b,g,r)的值,更改画笔的颜色,b=蓝色,g=绿色,r=红色。
# flags:绘图功能的标识设置,标识如下:
# cv2.DRAW_MATCHES_FLAGS_DEFAULT 默认值
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
# cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG
# cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS
img = cv2.drawKeypoints(image=img, outImage=img, keypoints = keypoints, flags=cv2.DRAW_MATCHES_FLAGS_DEFAULT, color = (51, 163, 236))

# 显示图片
cv2.imshow('sift_keypoints', img)
while (True):
 if cv2.waitKey(120) & 0xff == ord("q"):
  break
cv2.destroyAllWindows()

运行代码,结果如图所示:

Python使用Opencv实现图像特征检测与匹配的方法

除了SIFT算法检测之外,还有SURF特征检测算法,比SIFT算法快,并吸收了SIFT算法的思想。SURF采用Hessian算法检测关键点,而SURF是提取特征,这个与SIFT很像。Opencv的SURF类是Hessian算法和SURF算法组合。我们根据SIFT的代码进行修改,代码如下:

import cv2
# 读取图片并灰度处理
imgpath = 'varese.jpg'
img = cv2.imread(imgpath)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建SURF对象,对象参数float(4000)为阈值,阈值越高,识别的特征越小。
sift = cv2.xfeatures2d.SURF_create(float(4000))
# 将图片进行SURF计算,并找出角点keypoints,keypoints是检测关键点
# descriptor是描述符,这是图像一种表示方式,可以比较两个图像的关键点描述符,可作为特征匹配的一种方法。
keypoints, descriptor = sift.detectAndCompute(gray, None)

# cv2.drawKeypoints() 函数主要包含五个参数:
# image: 原始图片
# keypoints:从原图中获得的关键点,这也是画图时所用到的数据
# outputimage:输出
# color:颜色设置,通过修改(b,g,r)的值,更改画笔的颜色,b=蓝色,g=绿色,r=红色。
# flags:绘图功能的标识设置,标识如下:
# cv2.DRAW_MATCHES_FLAGS_DEFAULT 默认值
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
# cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG
# cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS
img = cv2.drawKeypoints(image=img, outImage=img, keypoints = keypoints, flags=cv2.DRAW_MATCHES_FLAGS_DEFAULT, color = (51, 163, 236))

# 显示图片
cv2.imshow('sift_keypoints', img)
while (True):
 if cv2.waitKey(120) & 0xff == ord("q"):
  break
cv2.destroyAllWindows()

上述代码我们只修改sift = cv2.xfeatures2d.SURF_create(float(4000))即可实现SURF特征检测算法。运行结果如图所示:

Python使用Opencv实现图像特征检测与匹配的方法

对比SURF和SIFT算法,ORB算法更处于起步阶段,在2011年才首次发布。但比前两者的速度更快。ORB基于FAST关键点检测和BRIEF的描述符技术相结合,因此我们先了解FAST和BRIEF。

FAST:特征检测算法。

BRIEF:只是一个描述符,这是图像一种表示方式,可以比较两个图像的关键点描述符,可作为特征匹配的一种方法。

暴力匹配:比较两个描述符并产生匹配结果。

在上述的例子中,我们只是将检测的关键点进行勾画,在这例子中,将使用ORB检测关键点之外,还将两图进行匹配,匹配的图像如下:

Python使用Opencv实现图像特征检测与匹配的方法

实现方法:首先分别对两图进行ORB处理,然后将两图的关键点进行暴力匹配。具体代码如下:

# ORB算法实现特征检测+暴力匹配

import numpy as np
import cv2
from matplotlib import pyplot as plt

# 读取图片内容
img1 = cv2.imread('aa.jpg',0)
img2 = cv2.imread('bb.png',0)

# 使用ORB特征检测器和描述符,计算关键点和描述符
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)


# 暴力匹配BFMatcher,遍历描述符,确定描述符是否匹配,然后计算匹配距离并排序
# BFMatcher函数参数:
# normType:NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2。
# NORM_L1和NORM_L2是SIFT和SURF描述符的优先选择,NORM_HAMMING和NORM_HAMMING2是用于ORB算法
bf = cv2.BFMatcher(normType=cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1,des2)
matches = sorted(matches, key = lambda x:x.distance)
# matches是DMatch对象,具有以下属性:
# DMatch.distance - 描述符之间的距离。 越低越好。
# DMatch.trainIdx - 训练描述符中描述符的索引
# DMatch.queryIdx - 查询描述符中描述符的索引
# DMatch.imgIdx - 训练图像的索引。

# 使用plt将两个图像的匹配结果显示出来
img3 = cv2.drawMatches(img1=img1,keypoints1=kp1,img2=img2,keypoints2=kp2, matches1to2=matches, outImg=img2, flags=2)
plt.imshow(img3),plt.show()

运行结果如图所示:

Python使用Opencv实现图像特征检测与匹配的方法

# SURF和SIFT算法+暴力匹配

暴力匹配BFMatcher是一种匹配方法,只要提供两个关键点即可实现匹配。若将上述例子改为SURF和SIFT算法,只需修改以下代码:

将orb = cv2.ORB_create()改为
orb = cv2.xfeatures2d.SURF_create(float(4000))

将bf = cv2.BFMatcher(normType=cv2.NORM_HAMMING, crossCheck=True)改为
bf = cv2.BFMatcher(normType=cv2.NORM_L1, crossCheck=True)

# 获取匹配关键点的坐标位置

在上述例子中,matches是DMatch对象,DMatch是以列表的形式表示,每个元素代表两图能匹配得上的点。如果想获取某个点的坐标位置,在上述例子添加以下代码:

# 由于匹配顺序是:matches = bf.match(des1,des2),先des1后des2。
# 因此,kp1的索引由DMatch对象属性为queryIdx决定,kp2的索引由DMatch对象属性为trainIdx决定

# 获取aa.jpg的关键点位置
x,y = kp1[matches[0].queryIdx].pt
cv2.rectangle(img1, (int(x),int(y)), (int(x) + 5, int(y) + 5), (0, 255, 0), 2)
cv2.imshow('a', img1)

# 获取bb.png的关键点位置
x,y = kp2[matches[0].trainIdx].pt
cv2.rectangle(img2, (int(x1),int(y1)), (int(x1) + 5, int(y1) + 5), (0, 255, 0), 2)
cv2.imshow('b', img2)

# 使用plt将两个图像的第一个匹配结果显示出来
img3 = cv2.drawMatches(img1=img1,keypoints1=kp1,img2=img2,keypoints2=kp2, matches1to2=matches[:1], outImg=img2, flags=2)
plt.imshow(img3),plt.show()

运行结果如图所示:

Python使用Opencv实现图像特征检测与匹配的方法

上述讲到的暴力匹配是使用BFMatcher匹配器实现的,然后由match函数实现匹配。接下来讲解K-最近邻匹配(KNN),并在BFMatcher匹配下实现。在所有机器学习的算法中,KNN可能是最为简单的算法。针对上述例子,改为KNN匹配,实现代码如下:

import numpy as np
import cv2
from matplotlib import pyplot as plt

# 读取图片内容
img1 = cv2.imread('aa.jpg',0)
img2 = cv2.imread('bb.png',0)

# 使用ORB特征检测器和描述符,计算关键点和描述符
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)

# 暴力匹配BFMatcher,遍历描述符,确定描述符是否匹配,然后计算匹配距离并排序
# BFMatcher函数参数:
# normType:NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2。
# NORM_L1和NORM_L2是SIFT和SURF描述符的优先选择,NORM_HAMMING和NORM_HAMMING2是用于ORB算法
bf = cv2.BFMatcher(normType=cv2.NORM_HAMMING, crossCheck=True)
# knnMatch 函数参数k是返回符合匹配的个数,暴力匹配match只返回最佳匹配结果。
matches = bf.knnMatch(des1,des2,k=1)

# 使用plt将两个图像的第一个匹配结果显示出来
# 若使用knnMatch进行匹配,则需要使用drawMatchesKnn函数将结果显示
img3 = cv2.drawMatchesKnn(img1=img1,keypoints1=kp1,img2=img2,keypoints2=kp2, matches1to2=matches, outImg=img2, flags=2)
plt.imshow(img3),plt.show()

最后是介绍FLANN匹配,相对暴力匹配BFMatcher来讲,这匹配算法比较准确、快速和使用方便。FLANN具有一种内部机制,可以根据数据本身选择最合适的算法来处理数据集。值得注意的是,FLANN匹配器只能使用SURF和SIFT算法。
FLANN实现方式如下:

import numpy as np
import cv2
from matplotlib import pyplot as plt

queryImage = cv2.imread('aa.jpg',0)
trainingImage = cv2.imread('bb.png',0)

# 只使用SIFT 或 SURF 检测角点
sift = cv2.xfeatures2d.SIFT_create()
# sift = cv2.xfeatures2d.SURF_create(float(4000))
kp1, des1 = sift.detectAndCompute(queryImage,None)
kp2, des2 = sift.detectAndCompute(trainingImage,None)

# 设置FLANN匹配器参数
# algorithm设置可参考https://docs.opencv.org/3.1.0/dc/d8c/namespacecvflann.html
indexParams = dict(algorithm=0, trees=5)
searchParams = dict(checks=50)
# 定义FLANN匹配器
flann = cv2.FlannBasedMatcher(indexParams,searchParams)
# 使用 KNN 算法实现匹配
matches = flann.knnMatch(des1,des2,k=2)

# 根据matches生成相同长度的matchesMask列表,列表元素为[0,0]
matchesMask = [[0,0] for i in range(len(matches))]

# 去除错误匹配
for i,(m,n) in enumerate(matches):
  if m.distance < 0.7*n.distance:
    matchesMask[i] = [1,0]

# 将图像显示
# matchColor是两图的匹配连接线,连接线与matchesMask相关
# singlePointColor是勾画关键点
drawParams = dict(matchColor = (0,255,0),
          singlePointColor = (255,0,0),
          matchesMask = matchesMask,
          flags = 0)
resultImage = cv2.drawMatchesKnn(queryImage,kp1,trainingImage,kp2,matches,None,**drawParams)
plt.imshow(resultImage,),plt.show()

运行结果如图所示:

Python使用Opencv实现图像特征检测与匹配的方法

FLANN的单应性匹配,单应性是一个条件,该条件表面当两幅图像中的一副出像投影畸变时,他们还能匹配。FLANN的单应性实现代码如下:

import numpy as np
import cv2
from matplotlib import pyplot as plt

MIN_MATCH_COUNT = 10

img1 = cv2.imread('tattoo_seed.jpg',0)
img2 = cv2.imread('hush.jpg',0)

# 使用SIFT检测角点
sift = cv2.xfeatures2d.SIFT_create()
# 获取关键点和描述符
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

# 定义FLANN匹配器
index_params = dict(algorithm = 1, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
# 使用KNN算法匹配
matches = flann.knnMatch(des1,des2,k=2)

# 去除错误匹配
good = []
for m,n in matches:
  if m.distance < 0.7*n.distance:
    good.append(m)

# 单应性
if len(good)>MIN_MATCH_COUNT:
  # 改变数组的表现形式,不改变数据内容,数据内容是每个关键点的坐标位置
  src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
  dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
  # findHomography 函数是计算变换矩阵
  # 参数cv2.RANSAC是使用RANSAC算法寻找一个最佳单应性矩阵H,即返回值M
  # 返回值:M 为变换矩阵,mask是掩模
  M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
  # ravel方法将数据降维处理,最后并转换成列表格式
  matchesMask = mask.ravel().tolist()
  # 获取img1的图像尺寸
  h,w = img1.shape
  # pts是图像img1的四个顶点
  pts = np.float32([[0,0],[0,h-1],[w-1,h-1],[w-1,0]]).reshape(-1,1,2)
  # 计算变换后的四个顶点坐标位置
  dst = cv2.perspectiveTransform(pts,M)

  # 根据四个顶点坐标位置在img2图像画出变换后的边框
  img2 = cv2.polylines(img2,[np.int32(dst)],True,(255,0,0),3, cv2.LINE_AA)

else:
  print("Not enough matches are found - %d/%d") % (len(good),MIN_MATCH_COUNT)
  matchesMask = None

# 显示匹配结果
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
          singlePointColor = None,
          matchesMask = matchesMask, # draw only inliers
          flags = 2)
img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
plt.imshow(img3, 'gray'),plt.show()

运行结果如下所示:

Python使用Opencv实现图像特征检测与匹配的方法

单应性实际应用

从上述的例子可以看到,单应性是在两图片匹配的时候,其中某一图片发生变换处理,变换后图像会呈现一种立体空间的视觉效果,图像发生变换程度称为变换矩阵。以下例子将图像中的书本替换成其他书本,例子中所使用图片如下:

Python使用Opencv实现图像特征检测与匹配的方法

Python使用Opencv实现图像特征检测与匹配的方法

Python使用Opencv实现图像特征检测与匹配的方法

我们根据图1和图2计算变换矩阵,然后通过变换矩阵将图3进行变换,最后将图3加入到图1中,实现图片替换。实现代码如下:

import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('logo.jpg',0)
img2 = cv2.imread('book.jpg',0)

# 使用SIFT检测角点
sift = cv2.xfeatures2d.SIFT_create()
# 获取关键点和描述符
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

# 定义FLANN匹配器
index_params = dict(algorithm = 1, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
# 使用KNN算法匹配
matches = flann.knnMatch(des1,des2,k=2)

# 去除错误匹配
good = []
for m,n in matches:
  if m.distance < 0.7*n.distance:
    good.append(m)

# 单应性实际应用
# 改变数组的表现形式,不改变数据内容,数据内容是每个关键点的坐标位置
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
# findHomography 函数是计算变换矩阵
# 参数cv2.RANSAC是使用RANSAC算法寻找一个最佳单应性矩阵H,即返回值M
# 返回值:M 为变换矩阵,mask是掩模
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
# 获取img1的图像尺寸
h,w = img1.shape
# pts是图像img1的四个顶点
pts = np.float32([[0,0],[0,h-1],[w-1,h-1],[w-1,0]]).reshape(-1,1,2)
# 计算变换后的四个顶点坐标位置
dst = cv2.perspectiveTransform(pts,M)

# 图片替换
img3 = cv2.imread('aa.png',0)
# 降维处理
b = np.int32(dst).reshape(4, 2)
x,y = img2.shape
# 根据变换矩阵将图像img3进行变换处理
res = cv2.warpPerspective(img3, M, (y,x))
img_temp = img2.copy()
# 将图像img2的替换区域进行填充处理
cv2.fillConvexPoly(img_temp, b, 0)
# 将变换后的img3图像替换到图像img2
cv2.imshow('bb',img_temp)
res = img_temp + res
cv2.imshow('aa',res)
plt.imshow(res),plt.show()

运行结果如图所示:

Python使用Opencv实现图像特征检测与匹配的方法

从结果可以看到,替换后的图像周边出现黑色线条,这是正常的现象。在上图最左边的图bb可以看到,黑色区域是由图1和图2检测匹配所得的结果,如果匹配结果会存在一定的误差,这个误差是由多个因素所导致的。

在实际中,我们根据一张图片在众多的图片中查找匹配率最高的图片。如果按照上面的例子,也可以实现,但每次匹配时都需要重新检测图片的特征数据,这样会导致程序运行效率。因此,我们可以将图片的特征数据进行保存,每次匹配时,只需读取特征数据进行匹配即可。我们以下图为例:

Python使用Opencv实现图像特征检测与匹配的方法

Python使用Opencv实现图像特征检测与匹配的方法

我们根据图1在图2中查找最佳匹配的图片。首先获取图2的全部图片的特征数据,将代码保存在features.py:

import cv2
import numpy as np
from os import walk
from os.path import join

def create_descriptors(folder):
  files = []
  for (dirpath, dirnames, filenames) in walk(folder):
    files.extend(filenames)
  for f in files:
    if '.jpg' in f:
      save_descriptor(folder, f, cv2.xfeatures2d.SIFT_create())

def save_descriptor(folder, image_path, feature_detector):
  # 判断图片是否为npy格式
  if image_path.endswith("npy"):
    return
  # 读取图片并检查特征
  img = cv2.imread(join(folder,image_path), 0)
  keypoints, descriptors = feature_detector.detectAndCompute(img, None)
  # 设置文件名并将特征数据保存到npy文件
  descriptor_file = image_path.replace("jpg", "npy")
  np.save(join(folder, descriptor_file), descriptors)

if __name__=='__main__':
  path = 'E:\\anchors'
  create_descriptors(path)

运行代码,结果如图所示:

Python使用Opencv实现图像特征检测与匹配的方法

我们将图片的特征数据保存在npy文件。下一步是根据图1与这些特征数据文件进行匹配,从而找出最佳匹配的图片。代码存在matching.py:

from os.path import join
from os import walk
import numpy as np
import cv2

query = cv2.imread('tattoo_seed.jpg', 0)
folder = 'E:\\anchors'
descriptors = []
# 获取特征数据文件名
for (dirpath, dirnames, filenames) in walk(folder):
  for f in filenames:
    if f.endswith("npy"):
      descriptors.append(f)
  print(descriptors)

# 使用SIFT算法检查图像的关键点和描述符
sift = cv2.xfeatures2d.SIFT_create()
query_kp, query_ds = sift.detectAndCompute(query, None)

# 创建FLANN匹配器
index_params = dict(algorithm=0, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)

potential_culprits = {}
for d in descriptors:
  # 将图像query与特征数据文件的数据进行匹配
  matches = flann.knnMatch(query_ds, np.load(join(folder, d)), k=2)
  # 清除错误匹配
  good = []
  for m, n in matches:
    if m.distance < 0.7 * n.distance:
      good.append(m)
  # 输出每张图片与目标图片的匹配数目
  print("img is %s ! matching rate is (%d)" % (d, len(good)))
  potential_culprits[d] = len(good)

# 获取最多匹配数目的图片
max_matches = None
potential_suspect = None
for culprit, matches in potential_culprits.items():
  if max_matches == None or matches > max_matches:
    max_matches = matches
    potential_suspect = culprit

print("potential suspect is %s" % potential_suspect.replace("npy", "").upper())

代码运行后,输出结果如图所示:

Python使用Opencv实现图像特征检测与匹配的方法

从输出的结果可以看到,图1与图2的hush.jpg最为匹配,如图所示:

Python使用Opencv实现图像特征检测与匹配的方法

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现360皮肤按钮控件示例
Feb 21 Python
Python实现身份证号码解析
Sep 01 Python
Python OpenCV处理图像之图像直方图和反向投影
Jul 10 Python
想学python 这5本书籍你必看!
Dec 11 Python
python的pytest框架之命令行参数详解(上)
Jun 27 Python
Pytorch之view及view_as使用详解
Dec 31 Python
Python IDLE或shell中切换路径的操作
Mar 09 Python
Python reversed函数及使用方法解析
Mar 17 Python
Python如何省略括号方法详解
Mar 21 Python
Python日志logging模块功能与用法详解
Apr 09 Python
python3实现将json对象存入Redis以及数据的导入导出
Jul 16 Python
python中urllib包的网络请求教程
Apr 19 Python
Python OpenCV图像指定区域裁剪的实现
Oct 30 #Python
使用Python刷淘宝喵币(低阶入门版)
Oct 30 #Python
Python自动化完成tb喵币任务的操作方法
Oct 30 #Python
Flask框架 CSRF 保护实现方法详解
Oct 30 #Python
使用Python和OpenCV检测图像中的物体并将物体裁剪下来
Oct 30 #Python
python基于K-means聚类算法的图像分割
Oct 30 #Python
Python列表原理与用法详解【创建、元素增加、删除、访问、计数、切片、遍历等】
Oct 30 #Python
You might like
PHP语法速查表
2006/12/06 PHP
PHP版QQ互联OAuth示例代码分享
2015/07/05 PHP
PHP+MySQL之Insert Into数据插入用法分析
2015/09/27 PHP
PHP文件上传之多文件上传的实现思路
2016/01/27 PHP
PHP实现删除多重数组对象属性并重新赋值的方法
2017/06/07 PHP
小议Function.apply() 之一------(函数的劫持与对象的复制)
2006/11/30 Javascript
js 操作select与option(示例讲解)
2013/12/20 Javascript
Javascript 构造函数详解
2014/10/22 Javascript
jQuery实现鼠标经过图片变亮其他变暗效果
2015/05/08 Javascript
jQuery事件绑定on()、bind()与delegate() 方法详解
2015/06/03 Javascript
js如何判断访问是来自搜索引擎(蜘蛛人)还是直接访问
2015/09/14 Javascript
原生js编写autoComplete插件
2016/04/13 Javascript
微信小程序授权获取用户详细信息openid的实例详解
2017/09/20 Javascript
JavaScript html5 canvas实现图片上画超链接
2017/10/20 Javascript
移动web开发之touch事件实例详解
2018/01/17 Javascript
jquery引入外部CDN 加载失败则引入本地jq库
2018/05/23 jQuery
ng-repeat指令在迭代对象时的去重方法
2018/10/02 Javascript
微信小程序实现页面下拉刷新和上拉加载功能详解
2018/12/03 Javascript
JS防抖和节流实例解析
2019/09/24 Javascript
[08:02]DOTA2牵红线 zhou神抱得美人归
2014/03/22 DOTA
改进Django中的表单的简单方法
2015/07/17 Python
Python模拟登录验证码(代码简单)
2016/02/06 Python
python实现RSA加密(解密)算法
2016/02/17 Python
Python3操作SQL Server数据库(实例讲解)
2017/10/21 Python
详解用python写网络爬虫-爬取新浪微博评论
2019/05/10 Python
对Python中一维向量和一维向量转置相乘的方法详解
2019/08/26 Python
Python实现图片识别加翻译功能
2019/12/26 Python
Pytorch保存模型用于测试和用于继续训练的区别详解
2020/01/10 Python
pyspark给dataframe增加新的一列的实现示例
2020/04/24 Python
利用CSS3伪元素实现逐渐发光的方格边框
2017/05/07 HTML / CSS
手摸手教你用canvas实现给图片添加平铺水印的实现
2019/08/20 HTML / CSS
H&M旗下高端女装品牌:& Other Stories
2018/05/07 全球购物
编写类String 的构造函数、析构函数和赋值函数
2012/09/09 面试题
篮球比赛策划方案
2014/06/05 职场文书
2016年国庆节新闻稿范文
2015/11/25 职场文书
党风廉政建设心得体会(2016最新版)
2016/01/22 职场文书