opencv-python常用函数及其介绍

读取图片、显示图片、写回图片

# -*- coding: utf-8 -*-

import numpy as np
import cv2

print(cv2.__version__)


img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg', cv2.IMREAD_COLOR) #读入一副彩色图像。图像的透明度会被忽略 默认参数。
# img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg', cv2.IMREAD_GRAYSCALE) # Load an color image in grayscale 灰度
# img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg', cv2.IMREAD_UNCHANGED) # 包括图像的 alpha 通道

img = cv2.resize(img, (640, 480))

#
rows, cols, ch = img.shape
print('行/高:', rows, '列/宽:', cols, '通道:', ch)
# 图像的宽对应的是列数, 高对应的是行数。

cv2.namedWindow('image', cv2.WINDOW_NORMAL) # 可以调整窗口大小
# cv2.namedWindow('image', cv2.WINDOW_AUTOSIZE)#自动调整
# cv2.namedWindow('image', cv2.WINDOW_KEEPRATIO)#保持图片比例

# cv2.resizeWindow('image', 200, 200) # 不起作用?

cv2.imshow('image', img) # 窗口会自动调整为图像大小
# 在窗口上按任意键退出
cv2.waitKey(delay=0) # 返回按键的 ASCII 码值

cv2.destroyAllWindows()

#

# cv2.imwrite(‘/home/ltb/图片/cv2-tutorial/000001.png’, img)

颜色转化

# -*- coding: utf-8 -*-
# @Time : 2018/1/20 17:15
# @Author : play4fun
# @File : 颜色转换.py
# @Software: PyCharm

"""
颜色转换.py:
"""
import cv2

img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg', cv2.IMREAD_COLOR)
cv2.imshow("BGR", img)


gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow("GRAY", gray)


temp = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 灰色转RGB
cv2.imshow("RGB", temp)


cv2.waitKey(0)

图像通道顺序转换

import cv2
import numpy as np
from PIL import Image

path = "/home/ltb/1.jpg"
data = cv2.imread(path)
data = np.array(data)
data = np.transpose(data, (1, 2, 0))
img = Image.fromarray(data)
img.show()

读取视频流(单摄像头)

# -*- coding: utf-8 -*-
"""
Created on Fri Jan 3 21:06:22 2014
@author: duan
"""
'''
注意 当你的程序报错时 你 先检查的是你的摄像头是否能够在其他程 序中正常工作 比如 linux 下的 Cheese 。
'''


import numpy as np
import cv2
cap = cv2.VideoCapture(0) # 一般的笔 本电脑 有内置摄像头。所以参数就是 0。你可以 设置成 1 或 者其他的来 择别的摄像头


'''
你可以使用函数 cap.get(propId) 来获得 的一些参数信息。
propId 可以是 0 到 18 之 的任何整数。
其中的一些值可以使用 cap.set(propId,value) 来修改 value 就是 你想 置成的新值。
例如 我可以使用 cap.get(3) cv2.CAP_PROP_FRAME_WIDTH和 cap.get(4) cv2.CAP_PROP_FRAME_HEIGHT来查看每一帧的宽和高。
默认情况下得到的值是 640X480。但是我可以使用 ret=cap.set(3,320) 和 ret=cap.set(4,240) 来把宽和高改成 320X240。
'''
# ret=cap.set(3,320)
# ret=cap.set(4,240)

# ret = cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480)#避免计算量过大
# ret = cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 270)#
# 等比缩放
frame_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # 4 ,720
frame_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) # 3 ,1280
frame_height = int(480 / frame_width * frame_height) # 270
ret = cap.set(cv2.CAP_PROP_FRAME_HEIGHT, frame_height) # 高
ret = cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480)


# while (True):
while cap.isOpened(): # 检查是否成功初始化,否则就 使用函数 cap.open()
# Capture frame-by-frame
ret, frame = cap.read() # ret 返回一个布尔值 True/False
# print('frame shape:',frame.shape)#(720, 1280, 3)

frame = cv2.flip(frame, flipCode=1) # 左右翻转,使用笔记本电脑摄像头才有用。
# flipCode:翻转方向:1:水平翻转;0:垂直翻转;-1:水平垂直翻转

# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# Display the resulting frame
cv2.imshow('frame', gray)
cv2.setWindowTitle('frame', 'COLOR_BGR2GRAY')

# Property=cv2.getWindowProperty('frame',0)#无用

# if cv2.waitKey(1) & 0xFF == ord('q'):#不行
# break
key = cv2.waitKey(delay=10)
if key == ord("q"):
break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

读取视频流(双摄像头)

# -*- coding: utf-8 -*-
# @Time : 2017/8/15 00:19
# @Author : play4fun
# @File : two_camera.py
# @Software: PyCharm

"""
two_camera.py:
"""

import cv2
import numpy as np

cap0 = cv2.VideoCapture(0)
cap1 = cv2.VideoCapture(1)
ret = cap0.set(3, 320)
ret = cap0.set(4, 240)
ret = cap1.set(3, 320)
ret = cap1.set(4, 240)

while cap0.isOpened() and cap1.isOpened():
ret0, frame0 = cap0.read()
ret1, frame1 = cap1.read()

if ret0:
cv2.imshow('frame0', frame0)
cv2.setWindowTitle('frame0', 'On Top')
if ret1:
cv2.imshow('frame1', frame1)
# cv2.moveWindow('frame1', x=frame0.shape[1], y=0)
cv2.moveWindow('frame1', x=320, y=40)

key = cv2.waitKey(delay=2)
if key == ord("q"):
break

# When everything done, release the capture
cap0.release()
cap1.release()
cv2.destroyAllWindows()

读取视频(影片)

import numpy as np
import cv2

cap = cv2.VideoCapture('/home/ltb/视频/simplescreenrecorder-2019-04-14_00.52.45.mkv')
# cap = cv2.VideoCapture('output.avi')
# cap = cv2.VideoCapture('Minions_banana.mp4')


# 帧率
fps = cap.get(cv2.CAP_PROP_FPS) # 25.0
print("Frames per second using video.get(cv2.CAP_PROP_FPS) : {0}".format(fps))
# 总共有多少帧
num_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
print('共有', num_frames, '帧')
#
frame_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
frame_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
print('高:', frame_height, '宽:', frame_width)

FRAME_NOW = cap.get(cv2.CAP_PROP_POS_FRAMES) # 第0帧
print('当前帧数', FRAME_NOW) # 当前帧数 0.0

# 读取指定帧,对视频文件才有效,对摄像头无效??
frame_no = 121
cap.set(1, frame_no) # Where frame_no is the frame you want
ret, frame = cap.read() # Read the frame
cv2.imshow('frame_no'+str(frame_no), frame)

FRAME_NOW = cap.get(cv2.CAP_PROP_POS_FRAMES)
print('当前帧数', FRAME_NOW) # 当前帧数 122.0

while cap.isOpened():
ret, frame = cap.read()
FRAME_NOW = cap.get(cv2.CAP_PROP_POS_FRAMES) # 当前帧数
print('当前帧数', FRAME_NOW)

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

cv2.imshow('frame', gray)
key = cv2.waitKey(1)
if key == ord("q"):
break

cap.release()
cv2.destroyAllWindows()

写回视频

import numpy as np
import cv2

cap = cv2.VideoCapture(0)
width = 640
ret = cap.set(3, width)
height = 480
ret = cap.set(4, height)

# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID') # opencv 3.0
# Error: 'module' object has no attribute 'VideoWriter_fourcc'
# fourcc=cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
#jpeg,h263,'m', 'p', '4', 'v'

#
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (width, height))

while cap.isOpened():
ret, frame = cap.read()
if ret is True:

frame = cv2.resize(frame, (640, 480))

# write the flipped frame
out.write(frame)

cv2.imshow('frame', frame)

else:
break

key = cv2.waitKey(1)
if key == ord("q"):
break

# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()

绘图函数

# -*- coding: utf-8 -*-
import numpy as np
import cv2

'''
• img: 你想 绘制图形的 幅图像。
• color: 形状的颜色。以RGB为例 需要传入一个元组BGR 例如 255,0,0
代表蓝色,第一个是蓝色通道,第二个是绿色通道,第三个是红色通道。对于灰度图只需要传入灰度值。
• thickness 线条的粗细。如果给一个闭合图形 置为 -1 那么这个图形
就会被填充。 默认值是 1.
• linetype 线条的类型, 8 连接,抗锯齿等。 默认情况是8 连接。cv2.LINE_AA
为抗锯齿 这样看起来会非常平滑。
'''

# Create a black image
img = np.zeros((512, 512, 3), np.uint8)

# Draw a diagonal blue line with thickness of 5 px
cv2.line(img, pt1=(0, 0), pt2=(511, 511), color=(255, 0, 0), thickness=5) # pt1, pt2, color, thickness=
# cv2.polylines() 可以 用来画很多条线。只需要把想 画的线放在一 个列表中, 将 列表传给函数就可以了。每条线 会被独立绘制。 这会比用 cv2.line() 一条一条的绘制 要快一些。
# cv2.polylines(img, pts, isClosed, color, thickness=None, lineType=None, shift=None)
cv2.arrowedLine(img, pt1=(21, 13), pt2=(151, 401), color=(255, 0, 0), thickness=5)

cv2.rectangle(img, (384, 0), (510, 128), (0, 255, 0), 3)

cv2.circle(img, center=(447, 63), radius=63, color=(0, 0, 255), thickness=-1) # center, radius, color, thickness=None

# 一个参数是中心点的位置坐标。 下一个参数是长轴和短轴的长度。椭圆沿逆时针方向旋转的角度。
# 椭圆弧演顺时针方向起始的角度和结束角度 如果是 0 很 360 就是整个椭圆
cv2.ellipse(img, center=(256, 256), axes=(100, 50), angle=0, startAngle=0, endAngle=180, color=255,
thickness=-1) # center, axes, angle, startAngle, endAngle, color, thickness=

pts = np.array([[10, 5], [20, 30], [70, 20], [50, 10]], np.int32)
pts = pts.reshape((-1, 1, 2))
# 这里 reshape 的第一个参数为-1, 表明这一维的长度是根据后面的维度的计算出来的。
# 注意 如果第三个参数是 False 我们得到的多边形是不闭合的 ,首 尾不相 连 。

font = cv2.FONT_HERSHEY_SIMPLEX
# org :Bottom-left corner of the text string in the image.左下角
# 或使用 bottomLeftOrigin=True,文字会上下颠倒
cv2.putText(img, text='bottomLeftOrigin', org=(10, 400), fontFace=font, fontScale=1, color=(255, 255, 255), thickness=1, bottomLeftOrigin=True) # text, org, fontFace, fontScale, color, thickness=
cv2.putText(img, text='OpenCV', org=(10, 500), fontFace=font, fontScale=4, color=(255, 255, 255), thickness=2) # text, org, fontFace, fontScale, color, thickness=

# 所有的绘图函数的返回值都是 None ,所以不能使用 img = cv2.line(img,(0,0),(5

winname = 'example'
cv2.namedWindow(winname, 0)
cv2.imshow(winname, img)

cv2.imwrite("example.png", img)

cv2.waitKey(0)
cv2.destroyAllWindows()

拆分通道、合并通道

# -*- coding: utf-8 -*-
import cv2
import numpy as np
# 拆分及合并图像通道

img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg')

#
b, g, r = cv2.split(img) # 比较耗时的操作,请使用numpy 索引
img = cv2.merge((b, g, r))
#
b = img[:, :, 0]

# 使所有像素的红色通道值都为 0,你不必先拆分再赋值。
# 你可以 直接使用 Numpy 索引,这会更快。
img[:, :, 2] = 0

# 保存到文件,看下效果
cv2.imwrite(filename='split_color2.jpg', img=img)

图像相加

# -*- coding: utf-8 -*-
import cv2
import numpy as np

# 学习图像上的算术运算 加法 减法 位运算等

# 你可以使用函数 cv2.add() 将两幅图像进行加法运算 当然也可以直接使 用 numpy ,
# res=img1+img
# 两幅图像的大小 类型必须一致 ,或者第二个 图像可以使一个简单的标量值。


x = np.uint8([250])
y = np.uint8([10])
print(cv2.add(x, y)) # 250+10 = 260 => 255
# [[255]]
print(x + y) # 250+10=260%256=4
# [4]


# 图像混合
img1 = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg')
img2 = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.png')

dst = cv2.addWeighted(img1, 0.1, img2, 0.9, 0) # 第一幅图的权重是 0.7 第二幅图的权重是 0.3

cv2.imshow('dst', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像扩展缩放

# -*- coding: utf-8 -*-

'''
扩展缩放
在缩放时我们推荐使用 cv2.INTER_AREA
在扩展时我们推荐使用 v2.INTER_CUBIC 慢) 和 v2.INTER_LINEAR。
默认情况下所有改变图像尺寸大小的操作使用的插值方法 是 cv2.INTER_LINEAR。
Resize(src, dst, interpolation=CV_INTER_LINEAR)
'''

import cv2
import numpy as np

img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg')
# 下面的 None 本应 是 出图像的尺寸 但是因为后边我们设置了缩放因子
# 因此这里为 None
res = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)

# OR
# 我们直接设置输出图像的尺寸 所以不用设置缩放因子
# height, width = img.shape[:2]
# res = cv2.resize(img, (2 * width, 2 * height), interpolation=cv2.INTER_CUBIC)

cv2.imshow('resize', res)
cv2.imshow('src img', img)

cv2.waitKey(0)
cv2.destroyAllWindows()

Otsu二值化

# -*- coding: utf-8 -*-
'''
Otsu's 二值化
在第一 分中我们提到 retVal 当我们使用 Otsu 二值化时会用到它。 么它到底是什么呢
在使用全局 值时 我们就是 便给了一个数来做 值 我们怎么知 我们 取的 个数的好坏呢?
答案就是不停的尝 。
如果是一副双峰图像 ,简 单来 双峰图像是指图像直方图中存在两个峰 呢 ?
我们岂不是应 在两个峰 之 的峰 一个值作为阈值 。
就是 Otsu 二值化 做的。
简单来说,就是对一副双峰图像自动根据其直方图计算出一个阈值。
对于非双峰图像 这 种方法 得到的结果可能会不理想 。
这里 用到的函数 是 cv2.threshold() 但是 需要多传入一个参数 flag cv2.THRESH_OTSU。
这时 把 值 为 0。然后算法会找到最 优阈值 ,这 个最优 值就是 回值 retVal。
如果不使用 Otsu 二值化 返回的retVal 值与 设定的 阈值相等。
下 的例子中 输入图像是一副带有噪声的图像。
第一种方法 我们 设127 为全局 阈值。
第二种方法 我们直接使用 Otsu 二值化。
第三种方法 我 们 先使用一个 5x5 的 高斯核 去噪 然后再使用 Otsu 二值化。
看看噪音 去除对结果的影响有多大吧。
'''

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

img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg', 0)
# global thresholding
ret1, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# Otsu's thresholding
ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# Otsu's thresholding after Gaussian filtering
# 5,5 为 斯核的大小 0 为标准差
blur = cv2.GaussianBlur(img, (5, 5), 0)
# 阀值一定为 0
ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# plot all the images and their histograms
images = [img, 0, th1,
img, 0, th2,
blur, 0, th3]
titles = ['Original Noisy Image', 'Histogram', 'Global Thresholding (v=127)',
'Original Noisy Image', 'Histogram', "Otsu's Thresholding",
'Gaussian filtered Image', 'Histogram', "Otsu's Thresholding"]
# 使用了 pyplot 中画直方图的方法 plt.hist,
# 注意的是它的参数是一维数组
# 所以使用了 numpy ravel 方法 将多维数组 换成一维 也可以使用 flatten 方法
# ndarray.flat 1-D iterator over an array.
# ndarray.flatten 1-D array copy of the elements of an array in row-major order.

for i in range(3):
plt.subplot(3, 3, i * 3 + 1), plt.imshow(images[i * 3], 'gray')
plt.title(titles[i * 3]), plt.xticks([]), plt.yticks([])
plt.subplot(3, 3, i * 3 + 2), plt.hist(images[i * 3].ravel(), 256)
plt.title(titles[i * 3 + 1]), plt.xticks([]), plt.yticks([])
plt.subplot(3, 3, i * 3 + 3), plt.imshow(images[i * 3 + 2], 'gray')
plt.title(titles[i * 3 + 2]), plt.xticks([]), plt.yticks([])
plt.show()

自适应二值化

# -*- coding: utf-8 -*-

'''
自适应阈值
Adaptive Method- 指定 算阈值的方法。
– cv2.ADPTIVE_THRESH_MEAN_C 值取自相邻区域的平均值
– cv2.ADPTIVE_THRESH_GAUSSIAN_C 值取值相邻区域 的加权和 ,权重为一个高斯窗口
'''

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

img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.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 range(4):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])

plt.show()

简单二值化

# -*- coding: utf-8 -*-
'''
简单阈值
像素值高于阈值时 我们给这个像素 赋予一个新值, 可能是白色 ,
否则我们给它赋予另外一种颜色, 或是黑色 。
这个函数就是 cv2.threshhold()。
这个函数的第一个参数就是原图像
原图像应 是灰度图。
第二个参数就是用来对像素值进行分类的阈值。
第三个参数 就是当像素值高于, 有时是小于 阈值时应该被赋予的新的像素值。
OpenCV 提供了多种不同的阈值方法 , 是由第四个参数来决定的。
些方法包括
• cv2.THRESH_BINARY
• cv2.THRESH_BINARY_INV • cv2.THRESH_TRUNC
• cv2.THRESH_TOZERO
• cv2.THRESH_TOZERO_INV
'''

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

img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg', 0)

ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)

titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in range(6):
plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()

图像腐蚀

# -*- coding: utf-8 -*-
'''
两个基本的形态学操作是腐蚀和膨胀。他们 的变体构成了开运算 ,闭运算, 梯度等。
根据卷积核的大小 前景的所有像素 会 腐 掉 变为 0 ,所以前景物体会变小 整幅图像的白色区域会减少。
对于去除白噪声很有用 也可以用来断开两个 在一块的物体等。
'''

import cv2
import numpy as np

img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg', 0)
cv2.imshow('Origin', img)
print(img.shape)

#您可以将内核看作是一个小矩阵,我们在图像上滑动以进行(卷积)操作,例如模糊,锐化,边缘检测或其他图像处理操作。
kernel = np.ones((5, 5), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)

cv2.imshow('erode', erosion)
cv2.moveWindow('erode', x=img.shape[1], y=0)

cv2.waitKey(0)
cv2.destroyAllWindows()

图像膨胀

# -*- coding: utf-8 -*-
'''
与腐 相反 与卷积核对应的原图像的像素值中只 有一个是 1 中心元 素的像素值就是 1。所以 个操作会增加图像中的白色区域 前景 。一般在去 噪声时先用腐 再用膨胀。因为腐 在去掉白噪声的同时 也会使前景对 变 小。所以我们再对他 膨胀。 时噪声已经 去 了 不会再回来了 但是 前景 在并会增加。膨胀也可以用来 接两个分开的物体。
'''

import cv2
import numpy as np

img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg', 0)
cv2.imshow('Origin', img)
print(img.shape)

kernel = np.ones((5, 5), np.uint8)
dilation = cv2.dilate(img, kernel, iterations=1)

cv2.imshow('dilation', dilation)
cv2.moveWindow('dilation', x=img.shape[1], y=0)

cv2.waitKey(0)
cv2.destroyAllWindows()

图像匹配

# -*-coding:utf8-*-#
__author__ = 'play4fun'
"""
create time:15-10-24 下午5:46
原理
模板匹配是用来在一副大图中搜寻查找模版图像位置的方法。OpenCV 为 我们提供了函数 cv2.matchTemplate()。
和 2D 卷积一样 它也是用模板图像在输入图像 大图 上滑动 并在每一个位置对模板图像和与其对应的 输入图像的子区域 比较。
OpenCV 提供了几种不同的比较方法 细节 看 文档 。
返回的结果是一个灰度图像 每一个像素值 示了此区域与模板的匹配 程度。
如果输入图像的大小是 WxH
模板的大小是 wxh 输出的结果 的大小就是 W-w+1 H-h+1 。
当你得到这幅图之后 就可以使用函数 cv2.minMaxLoc() 来找到其中的最小值和最大值的位置了。
第一个值为矩形左上角的点 位置
w h 为 moban 模板矩形的宽和 。
这个矩形就是 找到的模板区域了。
"""

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

img = cv2.imread('../data/messi5.jpg', 0)
img2 = img.copy()
template = cv2.imread('../data/messi_face.jpg', 0)

w, h = template.shape[::-1]
# All the 6 methods for comparison in a list
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']

for meth in methods:
img = img2.copy()

# exec 语句用来执行储存在字符串或文件中的 Python 语句。
# 例如,我们可以在运行时生成一个包含 Python 代码的字符串,
# 然后使用 exec 语句执行这些语句。
# eval 语句用来计算存储在字符串中的有效 Python 表达式
method = eval(meth)
# Apply template Matching
res = cv2.matchTemplate(img, template, method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# 使用不同的比较方法,对结果的解释不同
# If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc

bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(img, top_left, bottom_right, 255, 2)

plt.subplot(121), plt.imshow(res, cmap='gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img, cmap='gray')
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.suptitle('method: ' + meth)
plt.show()

SIFT算法

# -*- coding: utf-8 -*-
# @Time : 2017/7/13 下午2:23
# @Author : play4fun
# @File : sift.py
# @Software: PyCharm

"""
sift.py:尺度不变特征变换
关键点 极值点 定位
"""

import cv2
import numpy as np

img = cv2.imread('/home/ltb/图片/cv2-tutorial/000001.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray, None)
img = cv2.drawKeypoints(gray, kp, img)

# 计算关键点描述符
# 使用函数 sift.compute() 来 计算 些关键点的描述符。例如
# kp, des = sift.compute(gray, kp)
kp, des = sift.detectAndCompute(gray, None)

cv2.imwrite('sift_keypoints.jpg', img)
cv2.imshow('sift_keypoints.jpg', img)
cv2.waitKey(0)
Author: pangzibo243
Link: https://litianbo243.github.io/2019/08/05/opencv-python常用函数及介绍/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
支付宝打赏
微信打赏