【python计算机视觉编程——10.OpenCV】

10.OpenCV

10.2 OpenCV基础知识

10.2.1 读取和写入图像

import cv2
from pylab import  *
im=cv2.imread('sun.jpg')
h,w=im.shape[:2]
print(h,w)

cv2.imwrite('result.png',im)

10.2.2 颜色空间

im=cv2.imread('sun.jpg')
# 创建灰度图像
# COLOR_BGR2GRAY、COLOR_BGR2RGB、COLOR_GRAY2BGR
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
imshow(gray)

在这里插入图片描述

10.2.3 显示图像及结果

import cv2
# 读取图像
im = cv2.imread('sun.jpg')
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)

# 计算积分图像
intim = cv2.integral(gray)

# 归一化并保存
intim = (255.0*intim) / intim.max()
cv2.imwrite('result.jpg',intim)
import cv2

# 读取图像
filename = 'sun.jpg'
im = cv2.imread(filename)
h,w = im.shape[:2]
# 泛洪填充
diff = (6,6,6)
mask = np.zeros((h+2,w+2),uint8)
cv2.floodFill(im,mask,(10,10), (255,255,0),diff,diff)
# 在OpenCV 窗口中显示结果
cv2.imshow('flood fill',im)
cv2.waitKey()
# 保存结果
cv2.imwrite('result.jpg',im)
from pylab import  *
im1=cv2.imread('result_10.2.3-1.jpg')
im2=cv2.imread('result_10.2.3-2.jpg')
gray()
subplot(121)
imshow(im1)
subplot(122)
imshow(im2)

在这里插入图片描述

import cv2

# 初始化 ORB 检测器
orb = cv2.ORB_create()

# 读取图像
image = cv2.imread('sun.jpg', cv2.IMREAD_GRAYSCALE)

# 检测关键点和描述符
keypoints, descriptors = orb.detectAndCompute(image, None)

# 在图像上绘制关键点
output_image = cv2.drawKeypoints(image, keypoints, None)

# 显示结果
cv2.imshow('ORB Keypoints', output_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

10.3 处理视频

10.3.1 视频输入

import cv2

#设置视频捕获
# cap = cv2.VideoCapture(0)                #可以是摄像头的索引
cap = cv2.VideoCapture('MARSCONCERT.mp4')  #也可以是视频的名称

if not cap.isOpened():
    print("无法打摄像机")
    exit()
    
while True:
    ret,im = cap.read()
    cv2.imshow('video_test',im)
    key = cv2.waitKey(10)
    if key == 27:  #Esc键退出
        break
    if key == ord(' '):  #空格抓拍
        cv2.imwrite('vid_result.jpg',im)
        
# 释放摄像头并关闭所有窗口
cap.release()
cv2.destroyAllWindows()

在这里插入图片描述

还可以对实时显示的图像进行模糊

import cv2

# 1. 捕获视频
cap = cv2.VideoCapture('MARSCONCERT.mp4')  # 0通常代表默认的摄像头,也可以替换为视频文件的路径

# 检查摄像头是否成功打开
if not cap.isOpened():
    print("Error opening video stream or file")
    exit()

# 2. 设置输出视频参数
# fourcc = cv2.VideoWriter_fourcc(*'XVID')  # 选择编码器
# out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480))  # 输出视频文件名、编码器、帧率、分辨率

# 3. 读取并处理帧
while(cap.isOpened()):
    ret, frame = cap.read()  # 读取一帧
    if ret == True:
        blur = cv2.GaussianBlur(frame,(0,0),5)
        
        # 将处理后的帧写入输出视频
        # out.write(gray)

        # 显示帧(可选)
        cv2.imshow('frame', blur)
        
        key = cv2.waitKey(10)
        if key == 27:  #(Esc键)
            break
        if key == ord(' '):
            cv2.imwrite('vid_result.jpg',im)
    else:
        break

# 完成后释放资源
cap.release()
# out.release()
cv2.destroyAllWindows()

在这里插入图片描述

10.3.2 将视频读取到NumPy数组中

import cv2
import numpy as np
cap = cv2.VideoCapture('MARSCONCERT.mp4')

frames=[]
# 获取帧,存储到数组中
flag=0
while True:
    ret,im = cap.read()
    if flag==0:
        print(im.shape)
        flag=1
    if ret == True:
        cv2.imshow('video',im)
        frames.append(im)
        if cv2.waitKey(10) == 27:
            print(im.shape)
            break
    else:
        break
frames = np.array(frames)

# 检查尺寸
print(frames.shape)

# 完成后释放资源
cap.release()
cv2.destroyAllWindows()  # 有帧数、帧高、帧宽及颜色通道数(3个),共记录了181帧

在这里插入图片描述

10.4 跟踪

10.4.1 光流

  • 光流法主要依赖于三个假设。
    1. 亮度恒定:图像中目标的像素强度在连续帧之间不会发生变化。
    2. 时间规律:相邻帧之间的时间足够短,以至于在考虑运行变化时可以忽略它们之 间的差异。该假设用于导出下面的核心方程。
    3. 空间一致性:相邻像素具有相似的运动。
import cv2
import numpy as np
def draw_flow(im,flow,step=16):
    """ 在间隔分开的像素采样点处绘制光流"""
    h,w = im.shape[:2]  # 获取图像的高度和宽度
    y,x = np.mgrid[step/2:h:step,step/2:w:step].reshape(2,-1) # 生成间隔分开的采样点坐标
    y, x = y.astype(np.int32), x.astype(np.int32)  # 转换为整数类型
    
    # print(y,x)
    fx,fy = flow[y,x].T  # 获取每个采样点的光流向量分量
    
    # 创建线的终点
    lines = np.vstack([x,y,x+fx,y+fy]).T.reshape(-1,2,2)
    lines = np.int32(lines)
    
    # 创建图像并绘制
    vis = cv2.cvtColor(im,cv2.COLOR_GRAY2BGR) # 将灰度图像转换为彩色图像
    for (x1,y1),(x2,y2) in lines:
        cv2.line(vis,(x1,y1),(x2,y2),(0,255,0),1)  # 绘制光流的线条
        cv2.circle(vis,(x1,y1),1,(0,255,0), -1)    # 在起点绘制小圆点
    return vis
# 设置视频捕获
cap = cv2.VideoCapture('小镇里的花.mp4')
ret,im = cap.read()
prev_gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)

while True:
    # 获取灰度图像
    ret,im = cap.read()
    gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
    #计算流 
    flow = cv2.calcOpticalFlowFarneback(prev_gray,gray,None,0.5,3,15,3,5,1.2,0)
    prev_gray = gray
    #画出流矢量 
    cv2.imshow('Optical flow',draw_flow(gray,flow))
    if cv2.waitKey(10) == 27:
        break
cap.release()
cv2.destroyAllWindows()

在这里插入图片描述

10.4.2 Lucas-Kanade算法

import cv2

# 一些常数及默认参数
lk_params = dict(winSize=(15,15),maxLevel=2,
                 criteria=(cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT,10,0.03))
subpix_params = dict(zeroZone=(-1,-1),winSize=(10,10),
                     criteria = (cv2.TERM_CRITERIA_COUNT|cv2.TERM_CRITERIA_EPS,20,0.03))
feature_params = dict(maxCorners=500,qualityLevel=0.01,minDistance=10)

class LKTracker(object):
    """用金字塔光流Lucas-Kanade跟踪类"""
    def __init__(self,imnames):
        """ 使用图像名称列表初始化"""
        self.imnames = imnames
        self.features = []
        self.tracks = []
        self.current_frame = 0
    def detect_points(self):
        """ 利用子像素精确度在当前帧中检测“利于跟踪的好的特征”(角点) """
        #载入图像并创建灰度图像
        self.image = cv2.imread(self.imnames[self.current_frame])
        self.gray = cv2.cvtColor(self.image,cv2.COLOR_BGR2GRAY)
        #搜索好的特征点
        features = cv2.goodFeaturesToTrack(self.gray, **feature_params)
        #提炼角点位置
        cv2.cornerSubPix(self.gray,features, **subpix_params)
        self.features = features
        self.tracks = [[p] for p in features.reshape((-1,2))]
        self.prev_gray = self.gray
        
    def track_points(self):
        """ 跟踪检测到的特征""" 
        if self.features != []:
            self.step() # 移到下一帧
            # 载入图像并创建灰度图像
            self.image = cv2.imread(self.imnames[self.current_frame])
            self.gray = cv2.cvtColor(self.image,cv2.COLOR_BGR2GRAY)
            # reshape() 操作,以适应输入格式
            tmp = np.float32(self.features).reshape(-1, 1, 2)
            # 计算光流
            features,status,track_error = cv2.calcOpticalFlowPyrLK(self.prev_gray,
                                                                   self.gray,tmp,None,**lk_params)
            # 去除丢失的点
            self.features = [p for (st,p) in zip(status,features) if st]
            # 从丢失的点清楚跟踪轨迹
            features = np.array(features).reshape((-1,2))
            for i,f in enumerate(features):
                self.tracks[i].append(f)
            ndx = [i for (i,st) in enumerate(status) if not st]
            ndx.reverse()# 从后面移除
            for i in ndx:
                self.tracks.pop(i) 
            self.prev_gray = self.gray
    def step(self,framenbr=None):
        """ 移到下一帧。如果没有给定参数,直接移到下一帧"""
        if framenbr is None:
            self.current_frame = (self.current_frame + 1) % len(self.imnames)
        else:
            self.current_frame = framenbr % len(self.imnames)
    def draw(self):
        """用OpenCV 自带的画图函数画出当前图像及跟踪点,按任意键关闭窗口""" 
        # 用绿色圆圈画出跟踪点
        for point in self.features:
            cv2.circle(self.image,(int(point[0][0]),int(point[0][1])),3,(0,255,0),-1)
        cv2.imshow('LKtrack',self.image)
        cv2.waitKey()
  • 使用跟踪器

import numpy as np
imnames = ['bt.003.pgm', 'bt.002.pgm', 'bt.001.pgm', 'bt.000.pgm']

# 创建跟踪对象
lkt = LKTracker(imnames)
# 在第一帧进行检测,跟踪剩下的帧
lkt.detect_points()
lkt.draw()
for i in range(len(imnames)-1):
    lkt.track_points()
    lkt.draw()

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 使用发生器

将下面的方法添加到LKTracker类:

    def track(self):
        """ 发生器,用于遍历整个序列""" 
        for i in range(len(self.imnames)):
            if self.features == []:
                self.detect_points()
            else:
                self.track_points()
        # 创建一份RGB副本
        f = array(self.features).reshape(-1,2)
        im = cv2.cvtColor(self.image,cv2.COLOR_BGR2RGB)
        yield im,f
from pylab import *
imnames = ['viff.000.ppm', 'viff.001.ppm','viff.002.ppm', 'viff.003.ppm', 'viff.004.ppm']
# 用LKTracker 发生器进行跟踪
lkt = LKTracker(imnames)
for im,ft in lkt.track():
    print('tracking %d features' % len(ft))
# 画出轨迹
figure()
imshow(im)
for p in ft:
    plot(p[0],p[1],'bo')
for t in lkt.tracks:
    plot([p[0] for p in t],[p[1] for p in t])
axis('off')
show()

在这里插入图片描述

10.5 更多示例

10.5.1图像修复

import numpy as np
import cv2
 
#读取图片
img = cv2.imread('repair.png')
#图像转换为灰度图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#灰度二值化
_,mask = cv2.threshold(cv2.cvtColor(img,cv2.COLOR_BGR2GRAY),100,255,cv2.THRESH_BINARY_INV)
dst = cv2.inpaint(img,mask,10,cv2.INPAINT_NS) #3:领域大小
cv2.imshow('img0',img)
#cv2.imshow('img10',mask1)
cv2.imshow('img1',mask)
cv2.imshow('img2',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

下图为修复前的图像

在这里插入图片描述

下图为掩模图

在这里插入图片描述

下图为修复图像,可以看到,虽然黑线被修复了,但是整体图像中,原本不需要修复的地方,会被修复函数当作是需要修复的

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值