参考博客:https://www.jianshu.com/p/58c6ca1b66af
1. 视频产生图片
#! /usr/bin/env python import cv2 import os import glob def video2imgs(videoPath, savePicturePath): # imgs_dir是图片所在文件夹路径 cap = cv2.VideoCapture(videoPath) # 视频路径 numFrame = 0 # 用于写出图片的命名 numFrame = numFrame # 从1开始,这根据自己需要调整 while True: if cap.grab(): # 如果成功获取图片 flag, frame = cap.retrieve() if not flag: print('no flag: flag, frame = cap.retrieve()') continue else: # cv2.imshow('video', frame) numFrame += 1 # 用于写出图片的命名 n = str(numFrame) # 字符化 n = n.zfill(8) # 这样就是八位数, 前面自动补充0 newPath = savePicturePath + n + ".jpg" # 输出图片的具体路径 = 输出图片的文件夹 + 图片名字.jpg print(n) cv2.imencode('.jpg', frame)[1].tofile(newPath) # 关于这个[1]暂时没有具体研究, 可以查看相关资料 if numFrame == 100: break else: print('no cap.grab()') break if cv2.waitKey(10) == 27: break if __name__ == '__main__': video2imgs( '/home/hp/zjc/nk_PyCharm/PyCharm_project/nk_fishbox/nk_background_sub/fish_video.avi', '/home/hp/zjc/nk_PyCharm/PyCharm_project/nk_fishbox/nk_background_sub/img/')
2. 100帧混合背景
# -*- coding=utf-8 -*- # Author: zjc # Creation Date:19-8-30 import matplotlib.pyplot as plt import numpy as np from PIL import Image import cv2 import os import glob # 读取帧数 img_number = 100 # 各帧的集合 all_img = [np.array(Image.open( '/home/hp/zjc/nk_PyCharm/PyCharm_project/nk_fishbox/nk_background_sub/img/' + str(i + 1).zfill( 8) + '.jpg', 'r')) for i in range(img_number)] # 帧的宽高 h = all_img[0].shape[0] v = all_img[0].shape[1] t = all_img[0].shape[2] # 计算得到背景 back_img = np.zeros((h, v, t)) for single_img in all_img: back_img += single_img back_img /= img_number img = back_img print('=>图片:', img) print('=>形状:', img.shape) print('=>类型:', type(img)) img = Image.fromarray(np.uint8(img)) img = img.convert('RGB') img.save('/home/hp/zjc/nk_PyCharm/PyCharm_project/nk_fishbox/nk_background_sub/background.jpg') # 保存背景 # Image.fromarray(back_img).convert('RGB').save( # # '/home/hp/zjc/nk_PyCharm/PyCharm_project/nk_fishbox/nk_background_sub/img//background.jpg') ''' # 原视频与背景逐帧相减后取绝对值 得到前景 front_img = np.array([i - back_img for i in all_img]) front_img = front_img.__abs__() # 前景二值化 设定阈值将前景像素值化为0或1 threshold_level = 50 threshold = np.full((h, v), threshold_level) front_img = np.array([i < threshold for i in front_img], dtype=np.int8)*255 # 在原帧上抠图 得到真实的前景 front_img = np.fmax(np.array(front_img), all_img) # 保存 for i in range(img_number): Image.fromarray(front_img[i]).convert('RGB').save('F:/output/'+str(i+1)+'.jpg') # 显示 loc_h = 6 loc_v = int(img_number / loc_h) for i in range(loc_h * loc_v): plt.subplot(loc_v, loc_h, i+1) plt.imshow(front_img[i], cmap='gray') plt.show() '''
00000001.jpg为例
3 重点解释
https://www.jianshu.com/p/18dabefa6778
1. PIL image转换成array
img = np.asarray(image)
或
img=np.array(image)
需要注意的是,如果出现read-only错误,并不是转换的错误,一般是你读取的图片的时候,默认选择的是"r","rb"模式有关。修正的办法: 手动修改图片的读取状态
img.flags.writeable = True # 将数组改为读写模式或者
im = Image.open("lena.jpg") # 显示图片 im.show() im = im.convert("L") data = im.getdata() data = np.matrix(data)
或者
im = np.array(pil_im)
2. array转换成image
方法1
from PIL import Image
Image.fromarray(np.uint8(img))注意img如果是uint16的矩阵而不转为uint8的话,Image.fromarray这句会报错 相当关键
File "/usr/local/lib/python2.7/site-packages/PIL/Image.py", line 1884, in fromarray
raise TypeError("Cannot handle this data type")
TypeError: Cannot handle this data type类似这个问题
PIL weird error after resizing image in skimage
因为:一般在PIL是uint8格式无符号8位整型
4 因为1000帧结果不好
我想提取一部分ROI放在另一部分鱼影子上
import matplotlib.pyplot as plt import numpy as np from PIL import Image # 读取帧数 img_number = 48 # 各帧的集合 all_img = [np.array(Image.open('F:/input/'+str(i+1)+'.jpg', 'r')) for i in range(img_number)] # 帧的宽高 h = all_img[0].shape[0] v = all_img[0].shape[1] # 计算得到背景 back_img = np.zeros((h, v)) for single_img in all_img: back_img += single_img back_img /= img_number # 保存背景 Image.fromarray(back_img).convert('RGB').save('F:/output/background.jpg') # 原视频与背景逐帧相减后取绝对值 得到前景 front_img = np.array([i - back_img for i in all_img]) front_img = front_img.__abs__() # 前景二值化 设定阈值将前景像素值化为0或1 threshold_level = 50 threshold = np.full((h, v), threshold_level) front_img = np.array([i < threshold for i in front_img], dtype=np.int8)*255 # 在原帧上抠图 得到真实的前景 front_img = np.fmax(np.array(front_img), all_img) # 保存 for i in range(img_number): Image.fromarray(front_img[i]).convert('RGB').save('F:/output/'+str(i+1)+'.jpg') # 显示 loc_h = 6 loc_v = int(img_number / loc_h) for i in range(loc_h * loc_v): plt.subplot(loc_v, loc_h, i+1) plt.imshow(front_img[i], cmap='gray') plt.show()
%将视频转换为图片 clear clc file_name = 'F:\input.avi'; %视频所在文件夹 obj = VideoReader(file_name); %读取视频文件 numFrames = obj.NumberOfFrames; %视频总的帧数 for k = 1: numFrames frame = read(obj,k); %imshow(frame); gray_frame = rgb2gray(frame); %若每一帧为彩色图片,转换为灰度图 imshow(frame); %显示每一帧图片 %保存每一帧图片 imwrite(gray_frame,strcat('F:\input\',num2str(k),'.jpg'),'jpg'); end