计算机视觉实验 - OpenCV

edwin99
edwin99
2024-02-03 22:12
79 阅读
0 评论
文章封面
目录
正在加载目录...

import cv2import matplotlib.pyplot as plt

import numpy as np

 

def display_images(l,titles=None,fontsize=12):

n=len(l)

fig,ax = plt.subplots(1,n)

for i,im in enumerate(l):

ax[i].imshow(im)

ax[i].axis('off')

if titles is not None:

ax[i].set_title(titles[i],fontsize=fontsize)

fig.set_size_inches(fig.get_size_inches()*n)

plt.tight_layout()

plt.show()

im = cv2.imread('data/braille.jpeg')

print(im.shape)

plt.imshow(im)

 

输出:

(242, 531, 3)

 

bw_im = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)

print(bw_im.shape)

plt.imshow(bw_im)

 

 

 

im = cv2.blur(bw_im,(3,3))

im = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 5,4)

im = cv2.medianBlur(im, 3)

_,im = cv2.threshold(im, 0, 255, cv2.THRESH_OTSU)

im = cv2.GaussianBlur(im, (3,3), 0)

_,im = cv2.threshold(im, 0, 255, cv2.THRESH_OTSU)

plt.imshow(im)

 

用特征抽取技术(SIFT,SURF,ORB)提取单个点:

orb = cv2.ORB_create(5000)

f,d = orb.detectAndCompute(im,None)

print(f"First 5 points: { [f[i].pt for i in range(5)]}")

 

输出:

First 5 points: [(307.20001220703125, 40.80000305175781), (297.6000061035156, 114.00000762939453), (423.6000061035156, 133.20001220703125), (242.40000915527344, 144.0), (103.68000793457031, 57.60000228881836)] 绘图: def plot_dots(dots):

img = np.zeros((250,500))

for x in dots:

cv2.circle(img,(int(x[0]),int(x[1])),3,(255,0,0))

plt.imshow(img)

 

pts = [x.pt for x in f]plot_dots(pts)

进一步分开字母:直接算min和max坐标

将字母对齐:用透视变换,坐标围出矩形,用对应的维度对齐

off = 5

src_pts = np.array([(min_x-off,min_y-off),(min_x-off,max_y+off),

(max_x+off,min_y-off),(max_x+off,max_y+off)])

w = int(max_x-min_x+off*2)

h = int(max_y-min_y+off*2)

dst_pts = np.array([(0,0),(0,h),(w,0),(w,h)])

ho,m = cv2.findHomography(src_pts,dst_pts)

trim = cv2.warpPerspective(im,ho,(w,h))

plt.imshow(trim)

将所有矩阵分离:

char_h = 36char_w = 24def slice(img):

dy,dx = img.shape

y = 0

while y+char_h<dy:

x=0

while x+char_w<dx:

# Skip empty lines

if np.max(img[y:y+char_h,x:x+char_w])>0:

yield img[y:y+char_h,x:x+char_w]

x+=char_w

y+=char_h

 

sliced = list(slice(trim))display_images(sliced)

处理视频,转成帧:

vid = cv2.VideoCapture('data/motionvideo.mp4')

 

c = 0frames = []

while vid.isOpened():

ret, frame = vid.read()

if not ret:

break

frames.append(frame)

c+=1

vid.release()

print(f"Total frames: {c}")

display_images(frames[::150])

转成灰阶(颜色对运动检测没什么作用,所有调成灰阶节能省时间),计算帧距离,绘图:

bwframes = [cv2.cvtColor(x,cv2.COLOR_BGR2GRAY) for x in frames]

diffs = [(p2-p1) for p1,p2 in zip(bwframes[:-1],bwframes[1:])]

diff_amps = np.array([np.linalg.norm(x) for x in diffs])plt.plot(diff_amps)

display_images(diffs[::150],titles=diff_amps[::150])

消除噪音:

def moving_average(x, w):

return np.convolve(x, np.ones(w), 'valid') / w

 

threshold = 13000

 

plt.plot(moving_average(diff_amps,10))plt.axhline(y=threshold, color='r', linestyle='-')

active_frames = np.where(diff_amps>threshold)[0]

 

def subsequence(seq,min_length=30):

ss = []

for i,x in enumerate(seq[:-1]):

ss.append(x)

if x+1 != seq[i+1]:

if len(ss)>min_length:

return ss

ss.clear()

 

sub = subsequence(active_frames)print(sub)

输出:

[195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322]

 

还原图像:

plt.imshow(frames[(sub[0]+sub[-1])//2])

 

 

plt.imshow(cv2.cvtColor(frames[(sub[0]+sub[-1])//2],cv2.COLOR_BGR2RGB))

 

 

用光流提取运动信息:

  1. 稠密光流:计算矢量场,显示每个像素的移动方向

  2. 稀疏光流:提取图像显著特征(边缘),逐帧追踪运动轨迹

 

计算稠密光流:

flows = [cv2.calcOpticalFlowFarneback(f1, f2, None, 0.5, 3, 15, 3, 5, 1.2, 0)

for f1,f2 in zip(bwframes[:-1],bwframes[1:])]

flows[0].shape

输出:

(180, 320, 2)

 

 

 

 

光流转换成极坐标,每个像素有方向和张量

def flow_to_hsv(flow):

hsvImg = np.zeros((flow.shape[0],flow.shape[1],3),dtype=np.uint8)

mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])

hsvImg[..., 0] = 0.5 * ang * 180 / np.pi

hsvImg[..., 1] = 255

hsvImg[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)

return cv2.cvtColor(hsvImg, cv2.COLOR_HSV2BGR)

 

start = sub[0]

stop = sub[-1]

print(start,stop)

 

frms = [flow_to_hsv(x) for x in flows[start:stop]]

display_images(frms[::25])

扩展阅读:

  1. 用光流实现手掌运动检测

  2. 识别宠物脸部实验

  3. 卷积神经网络PyTorch试水

  4. 卷积网络TensorFlow试水

 

评论区 (0)

登录后参与评论

暂无评论,抢沙发吧!