import cv2
import numpy as np
image = cv2.imread("poker.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #转化为灰度图
#选取图像的一个区域作为匹配模板,如下是一个菱形的区域
template = gray[75:105, 235:265]
#第三个参数是将图片标准化,防止外界环境影响。计算匹配度,计算结果更准确
match = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF_NORMED)
locations = np.where(match >= 0.9) #找出匹配系数大于0.9的匹配点
#求模板图片的长和宽,方便作图
w, h = template.shape[0:2]
#循环遍历每一个匹配点
for p in zip(*locations[::-1]):
x1, y1 = p[0], p[1]
x2, y2 = x1 + w, y1 + h
# 在原始图像上画框
cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imshow("image", image)
cv2.waitKey()
这里仅把图像大小相等的框了出来,要想把不同大小的匹配出来,可以设置图像大小来匹配。
图像的梯度就是图像的明暗变化
取水平和垂直方向上的明暗变化,再求出两个变化的平方和就得到了梯度
import cv2
gray = cv2.imread("opencv_logo.jpg", cv2.IMREAD_GRAYSCALE) #转化为灰度图
#拉普拉斯算子
laplacian = cv2.Laplacian(gray, cv2.CV_64F)
#Canny边缘检测
canny = cv2.Canny(gray, 100, 200) #设置梯度区间(100,200)
#像素梯度大于200,可以确定是一个边缘,小于100是非边缘,100-200待定
cv2.imshow("gray", gray)
cv2.imshow("laplacian", laplacian)
cv2.imshow("canny", canny)
cv2.waitKey()
Laplace算子的函数原型
dst = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
前两个是必须的参数:
第一个参数是需要处理的图像;
第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度
结果:
两个算法的优缺点:
Laplacian:对图像中的阶跃性边缘点定位准确,对噪声非常敏感,丢失一部分边缘的方向信息,造成一些不连续的检测边缘
Canny:不容易受噪声影响,能检测到真正的弱边缘,在edge函数中,最有效的边缘检测方法。使用两种不同的阈值分别检测边缘强度和若边缘且当若边缘与强边缘相连时,才将若边缘包含在输出图像中,更容易检测出若边缘。
从给出的图片可知,光照分布不均,很难确定一个固定阈值把他分离出来
两种方法:
1.手动设置阈值的方法
import cv2
gray = cv2.imread("bookpage.jpg", cv2.IMREAD_GRAYSCALE)
#阈值为10,最大灰度255
ret, binary = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY)
cv2.imshow("gray", gray)
cv2.imshow("binary", binary)
cv2.waitKey()
结果后面展示。
2.自适应阈值:
把图片分成多个区域,对每个区域独立计算阈值
threshold函数使用一个阈值对图像进行二值化
import cv2
gray = cv2.imread("bookpage.jpg", cv2.IMREAD_GRAYSCALE)
ret, binary = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY)
#
binary_adaptive=cv2.adaptiveThreshold(gray,255,
cv2.ADAPTIVE_THRESH_GASSIAN_C,cv2.THRESH_BINARY,115,1)
# 每个区域大小155个像素
ret1, binary_otsu = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
#常用的阈值算法,自动计算恰当的阈值,使得分离出的两个灰度分布差异最大化
cv2.imshow("gray", gray)
cv2.imshow("binary", binary)
cv2.imshow("adaptive", binary_adaptive)
cv2.imshow("otsu", binary_otsu)
cv2.waitKey()
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
这个函数大致意思就是把图片每个像素点作为中心取N*N的区域,然后计算这个区域的阈值,来决定这个像素点变0还是变255
src:需要进行二值化的一张灰度图像
maxValue:满足条件的像素点需要设置的灰度值。(将要设置的灰度值)
adaptiveMethod:自适应阈值算法。可选ADAPTIVE_THRESH_MEAN_C 或 ADAPTIVE_THRESH_GAUSSIAN_C
thresholdType:opencv提供的二值化方法,只能THRESH_BINARY或者THRESH_BINARY_INV
blockSize:要分成的区域大小,上面的N值,一般取奇数
当blockSize越大,参与计算阈值的区域也越大,细节轮廓就变得越少,整体轮廓越粗越明显
C:常数,每个区域计算出的阈值的基础上在减去这个常数作为这个区域的最终阈值,可以为负数
形态学算法:腐蚀和膨胀
这一节操作要基于图像二值化
import cv2
import numpy as np
gray = cv2.imread("opencv_logo.jpg", cv2.IMREAD_GRAYSCALE)
#先做阈值处理,这里用反向阈值,因为图片背景是白色,想让他变成黑色
_, binary = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
kernel = np.ones((5, 5), np.uint8)
#腐蚀操作
erosion = cv2.erode(binary, kernel)
#膨胀操作
dilation = cv2.dilate(binary, kernel)
cv2.imshow("binary", binary)
cv2.imshow("erosion", erosion)
cv2.imshow("dilation", dilation)
cv2.waitKey()
腐蚀与膨胀对于清理图像边缘细节很有帮助
交替使用腐蚀与膨胀能使我们更好的处理图片边缘部分。
如:
原图:
开运算是指先进行腐蚀操作,再进行膨胀操作
# 开运算:先腐蚀,再膨胀
import cv2
import numpy as np
img = cv2.imread('dige.png')
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv2.imshow('opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 闭:先膨胀,再腐蚀
img =cv2.imread('dige.png')
kernel = np.ones((5,5),np.uint8)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.imshow('closing', closing)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
#获取摄像头的指针
capture = cv2.VideoCapture(0)
while True:
ret, frame = capture.read()
cv2.imshow("camera", frame)
key = cv2.waitKey(1)
if key != -1:
break
capture.release(