opencv中的一些基础函数
1 年前
- 读入图片
cv2.imread()
- 显示图像
cv2.imshow()
- 保存图像
cv2.imwrite()
绘图函数
cv2.line() # 画线
cv2.circle() # 画矩形
cv2.rectangle() # 画圆
cv2.ellipse() # 画椭圆
cv2.putText() # 图片上添加文字
获取图像属性
图像的属性包括:行,列,通道,图像数据类型,像素数目等
img=cv2.imread('111.jpg')
print(img.shape, img.size, img.dtype)
拆分及合并图像通道
img=cv2.imread('111.jpg')
b,g,r=cv2.split(img)
img=cv2.merge(b,g,r)
图像混合
import cv2
import numpy as np
img1=cv2.imread('111.png')
img2=cv2.imread('222.jpg')
dst=cv2.addWeighted(img1,0.7,img2,0.3,0)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindow()
颜色空间转换
cv2.cvtColor()
cv2.inRange()
仿射变换
cv2.getAffineTransform
cv2.warpAffine
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('111.png')
rows,cols,ch=img.shape
pts1=np.float32([[50,50],[200,50],[50,200]])
pts2=np.float32([[10,100],[200,50],[100,250]])
M=cv2.getAffineTransform(pts1,pts2)
dst=cv2.warpAffine(img,M,(cols,rows))
plt.subplot(121,plt.imshow(img),plt.title('Input'))
plt.subplot(121,plt.imshow(img),plt.title('Output'))
plt.show()
透视变换
cv2.getPerspectiveTransform
cv2.warpPerspective
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('111.png')
rows,cols,ch=img.shape
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M=cv2.getPerspectiveTransform(pts1,pts2)
dst=cv2.warpPerspective(img,M,(300,300))
plt.subplot(121,plt.imshow(img),plt.title('Input'))
plt.subplot(121,plt.imshow(img),plt.title('Output'))
plt.show()
图像阈值
cv2.threshold # 简单阈值
cv2.adaptiveThreshold # 自适应阈值
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('111.jpg',0)
img = cv2.medianBlur(img,5) # 中值滤波
ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
#11 为 Block size, 2 为 C 值
th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,11,2)
th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2)
titles = ['Original Image', 'Global Thresholding (v = 127)', 'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]
for i in xrange(4):
plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
边界检测
逻辑:
① 5*5高斯滤波去噪
②使用sobel算子计算梯度
③非极大值抑制
④滞后阈值(minval、maxval)
img = cv2.imread('111.jpg',0)
edges = cv2.Canny(img,100,200) # 参数:输入图像,minVal,maxVal
轮廓
cv2.findContours() # 查找轮廓
cv2.drawContours() # 绘制轮廓
import cv2
import numpy as np
img = cv2.imread('111.jpg',0)
ret,thresh = cv2.threshold(img,127,255,0)
contours,hierarchy = cv2.findContours(thresh, 1, 2)
cnt = contours[0]
area = cv2.contourArea(cnt) # 轮廓面积
perimeter = cv2.arcLength(cnt,True) # 轮廓周长
k = cv2.isContourConvex(cnt) # 凸性检测
# 边界矩形
# 直边界矩形
x,y,w,h = cv2.boundingRect(cnt)
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
# 旋转的边界矩形
x,y,w,h = cv2.boundingRect(cnt)
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
# 最小外接圆
(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
img = cv2.circle(img,center,radius,(0,255,0),2)
# 椭圆拟合
cv2.ellipse()
# 直线拟合
rows,cols = img.shape[:2]
[vx,vy,x,y] = cv2.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
img = cv2.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)
# 比较两个形状或轮廓的相似度,返回值越小,匹配越好
cv2.matchShape()
import cv2
import numpy as np
img1 = cv2.imread('111.jpg',0)
img2 = cv2.imread('222.jpg',0)
ret, thresh = cv2.threshold(img1, 127, 255,0)
ret, thresh2 = cv2.threshold(img2, 127, 255,0)
contours,hierarchy = cv2.findContours(thresh,2,1)
cnt1 = contours[0]
contours,hierarchy = cv2.findContours(thresh2,2,1)
cnt2 = contours[0]
ret = cv2.matchShapes(cnt1,cnt2,1,0.0)
print(ret)
直方图
# 统计直方图
cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
# images: 原图像(图像格式为 uint8 或 float32)。当传入函数时应该用中括号 [] 括起来,例如:[img]。
# channels: 同样需要用中括号括起来,它会告诉函数我们要统计那幅图像的直方图。如果输入图像是灰度图,它的值就是 [0];如果是彩色图像的话,传入的参数可以是 [0],[1],[2] 它们分别对应着通道 B,G,R。
# mask: 掩模图像。要统计整幅图像的直方图就把它设为 None。但是如果你想统计图像某一部分的直方图的话,你就需要制作一个掩模图像,并使用它。(后边有例子)
# histSize:BIN 的数目。也应该用中括号括起来,例如:[256]。
# ranges: 像素值范围,通常为 [0,256]
img = cv2.imread('111.jpg',0) # 别忘了中括号,只有 mask 没有中括号
hist = cv2.calcHist([img],[0],None,[256],[0,256])
# 统计2D直方图
cv2.calcHist()
# 直方图反向投影
cv2.calcBackProject()
图像变换
傅里叶变换
cv2.dft()
cv2.idft()
模板匹配
cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
cv2.minMaxLoc()
Hough 直线变换
cv2.HoughLines()
cv2.HoughLinesP()
Hough 圆环变换
cv2.HoughCircles()
分水岭算法图像分割
cv2.watershed
使用 GrabCut 算法进行交互式前景提取
cv2.grabCut()
Harris 角点检测
cv2.cornerHarris(img, blockSize, ksize, k) # 角点检测
• img - 数据类型为 float32 的输入图像。
• blockSize - 角点检测中要考虑的领域大小。
• ksize - Sobel 求导中使用的窗口大小
• k - Harris 角点检测方程中的自由参数,取值参数为 [0,04,0.06]
cv2.cornerSubPix() # 亚像素级别的角点检测
import cv2 as cv
from matplotlib import pyplot as plt
import numpy as np
# detector parameters
block_size = 3
sobel_size = 3
k = 0.06
image = cv.imread('111.jpg')
print(image.shape)
height = image.shape[0]
width = image.shape[1]
channels = image.shape[2]
print("width: %s height: %s channels: %s"%(width, height, channels))
gray_img = cv.cvtColor(image, cv2.COLOR_BGR2GRAY)
# modify the data type setting to 32-bit floating point
gray_img = np.float32(gray_img)
# detect the corners with appropriate values as input parameters
corners_img = cv.cornerHarris(gray_img, block_size, sobel_size, k)
# result is dilated for marking the corners, not necessary
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
dst = cv.dilate(corners_img, kernel)
# Threshold for an optimal value, marking the corners in Green
#image[corners_img>0.01*corners_img.max()] = [0,0,255]
for r in range(height):
for c in range(width):
pix=dst[r,c]
if pix>0.05*dst.max():
cv2.circle(image,(c,r),5,(0,0,255),0)
image = cv.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(image)
plt.show()
Shi-Tomasi 角点检测 & 适合于跟踪的图像特征
cv2.goodFeatureToTrack()
关键点检测和描述:SIFT(Scale-Invariant Feature Transform)
import cv2
import numpy as np
img = cv2.imread('111.jpg')
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
sift = cv2.SIFT()
kp = sift.detect(gray,None) # 在图像中找关键点
img=cv2.drawKeypoints(gray,kp,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) # 在关键点部位绘制小圆圈
cv2.imwrite('sift_keypoints.jpg',img)
# 若是已知关键点,使用kp, des = sift.compute(gray, kp)来计算这些关键点的描述符
# 若还未找到关键点,使用sift.detectAndCompute()一步到位直接找到关键点并计算出其描述符。
关键点检测和描述:SURF(Speeded-Up Robust Features)
SURF.detect()
SURF.compute()
img = cv2.imread('111.png',0)
# Create SURF object. You can specify params here or later.
# Here I set Hessian Threshold to 400
surf = cv2.SURF(400)
# Find keypoints and descriptors directly
kp, des = surf.detectAndCompute(img,None)
print(len(kp)) # 699
# 在一幅图像中显示 699 个关键点太多了。我们把它缩减到 50 个再绘制到图片上。
print(surf.hessianThreshold) # 400.0
# We set it to some 50000. Remember, it is just for representing in picture.
# In actual cases, it is better to have a value 300-500
surf.hessianThreshold = 50000
# Again compute keypoints and check its number.
kp, des = surf.detectAndCompute(img,None)
print(len(kp)) # 47
img2 = cv2.drawKeypoints(img,kp,None,(255,0,0),4)
plt.imshow(img2)
plt.show()
角点检测的 FAST 算法
img = cv2.imread('111.jpg',0)
# Initiate FAST object with default values
fast = cv2.FastFeatureDetector()
# find and draw the keypoints
kp = fast.detect(img,None)
img2 = cv2.drawKeypoints(img, kp, color=(255,0,0))
# Print all default params
print("Threshold: ", fast.getInt('threshold'))
print("nonmaxSuppression: ", fast.getBool('nonmaxSuppression'))
print("neighborhood: ", fast.getInt('type'))
print("Total Keypoints with nonmaxSuppression: ", len(kp))
cv2.imwrite('fast_true.png',img2)
# Disable nonmaxSuppression
fast.setBool('nonmaxSuppression',0)
kp = fast.detect(img,None)
print("Total Keypoints without nonmaxSuppression: ", len(kp))
img3 = cv2.drawKeypoints(img, kp, color=(255,0,0))
cv2.imwrite('fast_false.png',img3)
BRIEF(Binary Robust Independent Elementary Features)
# BRIEF是一种特征描述符,不提供查找特征的方法,需要搭配其他的特征检测器
# 这里使用 CenSurE 特征检测器(STAR检测器)和 BRIEF 描述符
img = cv2.imread('111.jpg',0)
# Initiate STAR detector
star = cv2.FeatureDetector_create("STAR")
# Initiate BRIEF extractor
brief = cv2.DescriptorExtractor_create("BRIEF")
# find the keypoints with STAR
kp = star.detect(img,None)
# compute the descriptors with BRIEF
kp, des = brief.compute(img, kp)
print(brief.getInt('bytes'))
print(des.shape)
ORB (Oriented FAST and Rotated BRIEF)
img = cv2.imread('111.jpg',0)
# Initiate STAR detector
orb = cv2.ORB()
# find the keypoints with ORB
kp = orb.detect(img,None)
# compute the descriptors with ORB
kp, des = orb.compute(img, kp)
# draw only keypoints location,not size and orientation
img2 = cv2.drawKeypoints(img,kp,color=(0,255,0), flags=0)
plt.imshow(img2)
plt.show()
特征匹配
- 蛮力(Brute-Force)匹配
bf = cv2.BFMatcher()
bf.match() # 返回最佳匹配
bf.knnMatch() # 为每个关键点返回 k 个最佳匹配
# 对ORB描述符进行蛮力匹配
img1 = cv2.imread('111.png',0) # queryImage
img2 = cv2.imread('222.png',0) # trainImage
# Initiate SIFT detector
orb = cv2.ORB()
# find the keypoints and descriptors with SIFT
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)
# create BFMatcher object
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
# Match descriptors.
# 这里的返回值是DMatch 对象列表。具有以下属性:
• DMatch.distance - 描述符之间的距离。越小越好。
• DMatch.trainIdx - 目标图像中描述符的索引。
• DMatch.queryIdx - 查询图像中描述符的索引。
• DMatch.imgIdx - 目标图像的索引。
matches = bf.match(des1,des2)
# Sort them in the order of their distance.
matches = sorted(matches, key = lambda x:x.distance)
# 对 SIFT 描述符进行蛮力匹配和比值测试
img1 = cv2.imread('111.png',0) # queryImage
img2 = cv2.imread('222.png',0) # trainImage
# Initiate SIFT detector
sift = cv2.SIFT()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
# BFMatcher with default params
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2)
# Apply ratio test
# 比值测试,首先获取与 A 距离最近的点 B(最近)和 C(次近),只有当 B/C 小于阈值时(0.75)才被认为是匹配,因为假设匹配是一一对应的,真正的匹配的理想距离为 0
good = []
for m,n in matches:
if m.distance < 0.75*n.distance:
good.append([m])
# cv2.drawMatchesKnn expects list of lists as matches.
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good[:10],flags=2)
plt.imshow(img3)
plt.show()
- FLANN 匹配器(Fast_Library_for_Approximate_Nearest_Neighbors)
img1 = cv2.imread('111.png',0) # queryImage
img2 = cv2.imread('222.png',0) # trainImage
# Initiate SIFT detector
sift = cv2.SIFT()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
# FLANN parameters
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50) # or pass empty dictionary
flann = cv2.FlannBasedMatcher(index_params,search_params)
matches = flann.knnMatch(des1,des2,k=2)
# Need to draw only good matches, so create a mask
matchesMask = [[0,0] for i in xrange(len(matches))]
# ratio test as per Lowe's paper
for i,(m,n) in enumerate(matches):
if m.distance < 0.7*n.distance:
matchesMask[i]=[1,0]
draw_params = dict(matchColor = (0,255,0),singlePointColor = (255,0,0),matchesMask = matchesMask,flags = 0)
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params)
plt.imshow(img3,)
plt.show()
使用特征匹配和单应性查找对象
# 找到SIFT特征点病利用比值测试找到最佳匹配
import numpy as np
import cv2
from matplotlib import pyplot as plt
MIN_MATCH_COUNT = 10
img1 = cv2.imread('111.png',0) # queryImage
img2 = cv2.imread('222.png',0) # trainImage
# Initiate SIFT detector
sift = cv2.SIFT()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1,des2,k=2)
# store all the good matches as per Lowe's ratio test.
good = []
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
# 设置只有存在10个以上匹配时才去查找目标(MIN_MATCH_COUNT=10)
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)
# 第三个参数 Method used to computed a homography matrix. The following methods are possible:
# 0 - a regular method using all the points
# CV_RANSAC - RANSAC-based robust method
# CV_LMEDS - Least-Median robust method
# 第四个参数取值范围在 1 到 10,ᲁ绝一个点对的阈值。原图像的点经过变换后点与目标图像上对应点的误差
# 超过误差就认为是 outlier
# 返回值中 M 为变换矩阵。
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
matchesMask = mask.ravel().tolist()
# 获得原图像的高和宽
h,w = img1.shape
# 使用得到的变换矩阵对原图像的四个角进行变换,获得在目标图像上对应的坐标。
pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
dst = cv2.perspectiveTransform(pts,M)
# 原图像为灰度图
cv2.polylines(img2,[np.int32(dst)],True,255,10, cv2.LINE_AA)
else:
print("Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT))
matchesMask = None
# 最后绘制inliers(如果能成功的找到目标图像的话)或者匹配的关键点(如果失败)
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()
部分机器学习算法
- KNN
import cv2
import numpy as np
import matplotlib.pyplot as plt
# Feature set containing (x,y) values of 25 known/training data
trainData = np.random.randint(0,100,(25,2)).astype(np.float32)
# Labels each one either Red or Blue with numbers 0 and 1
responses = np.random.randint(0,2,(25,1)).astype(np.float32)
# Take Red families and plot them
red = trainData[responses.ravel()==0]
plt.scatter(red[:,0],red[:,1],80,'r','^')
# Take Blue families and plot them
blue = trainData[responses.ravel()==1]
plt.scatter(blue[:,0],blue[:,1],80,'b','s')
plt.show()
newcomer = np.random.randint(0,100,(1,2)).astype(np.float32)
plt.scatter(newcomer[:,0],newcomer[:,1],80,'g','o')
knn = cv2.KNearest()
knn.train(trainData,responses)
ret, results, neighbours ,dist = knn.find_nearest(newcomer, 3)
print("result: ", results,"\n")
print("neighbours: ", neighbours,"\n")
print("distance: ", dist)
plt.show()
- K值聚类
cv2.kmeans()
输入参数:
1. samples: np.float32 类型的数据,每个特征应该放在一列。
2. nclusters(K): 聚类的最终数目。
3. criteria: 终止迭代的条件。当条件满足时,算法的迭代终止。它应该是一个含有 3 个成员的元组,它们是(typw,max_iter,epsilon):
• type 终止的类型:有如下三种选择:
– cv2.TERM_CRITERIA_EPS 只有精确度 epsilon 满足时停止迭代。
– cv2.TERM_CRITERIA_MAX_ITER 当迭代次数超过阈值时停止迭代。
– cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER上面的任何一个条件满足时停止迭代。
• max_iter 表示最大迭代次数。
• epsilon 精确度阈值。
4. attempts: 使用不同的起始标记来执行算法的次数。算法会返回紧密度最好的标记。紧密度也会作为输出被返回。
5. flags:用来设置如何选择起始重心。通常我们有两个选择:cv2.KMEANS_PP_CENTERS和 cv2.KMEANS_RANDOM_CENTERS。
输出参数:
1. compactness:紧密度,返回每个点到相应重心的距离的平方和。
2. labels:标志数组(与上一节提到的代码相同),每个成员被标记为 0,1 等
3. centers:由聚类的中心组成的数组。
图像去噪
1. cv2.fastNlMeansDenoising() 使用对象为灰度图。
2. cv2.fastNlMeansDenoisingColored() 使用对象为彩色图。
3. cv2.fastNlMeansDenoisingMulti() 适用于短时间的图像序列(灰度图像)
4. cv2.fastNlMeansDenoisingColoredMulti() 适用于短时间的图像序列(彩色图像)
共同参数有:
• h : 决定过滤器强度。h 值高可以很好的去除噪声,但也会把图像的细节抹去。(取 10 的效果不错)
• hForColorComponents : 与 h 相同,但使用与彩色图像。(与 h 相同)
• templateWindowSize : 奇数。(推荐值为 7)
• searchWindowSize : 奇数。(推荐值为 21)
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('111.png')
dst = cv2.fastNlMeansDenoisingColored(img,None,10,10,7,21)
plt.subplot(121),plt.imshow(img)
plt.subplot(122),plt.imshow(dst)
plt.show()
图像修补
cv2.inpaint()
对象检测
- 使用 Haar 分类器进行面部检测
import numpy as np
import cv2
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
img = cv2.imread('333.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Detects objects of different sizes in the input image.
# The detected objects are returned as a list of rectangles.
#cv2.CascadeClassifier.detectMultiScale(image, scaleFactor, minNeighbors, flags, minSize, maxSize)
#scaleFactor – Parameter specifying how much the image size is reduced at each image scale.
#minNeighbors – Parameter specifying how many neighbors each candidate rectangle should have to retain it.
#minSize – Minimum possible object size. Objects smaller than that are ignored.
#maxSize – Maximum possible object size. Objects larger than that are ignored.
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)