使用python读取视频中的指定数字(一):视频分帧处理


写在前面:

  一个做传感器的朋友遇到了一个问题。他需要使用网络分析仪做一些测试,但是这个网络分析仪不能保存这些动态数据,以前采用的是这样的方法:先用手机录像,再用视频编辑软件一帧一帧的回放视频,手动把数据抄下来,比较麻烦。因此我想尝试用python写一段小程序,代替人工操作。如图是手机拍摄的视频其中一张截图,图中的 433.03500 Mhz 就是我们需要的数据,它1s内会变化几十次。

视频截图视频截图

  我的思路是先将视频分帧提取成图片,然后再识别数据,最后再保存。但是存在一个问题,视频中存在很多不需要的数字和文字,如果全部提取出来就很不好分类。所以我打算将提取出的图片分块,保留需要的图片块。如下图是整个流程的思维导图。

流程思维导图

  接下里就是各个部分的分别测试了,首先是视频分帧。我采用的是opencv。

  安装 opencv:打开 cmd 输入

pip install opencv-python

  这里给出 opencv 的官方文档链接:https://opencv-python-tutroals.readthedocs.io/en/latest/

  以下代码是将指定视频每一帧读取并安顺序命名保存,还是比较简单的。调试过程中没有遇到什么问题,就直接放在这里了。其中 frame 变量就是读取出的图片。需要将视频和代码放在一个文件夹下。

#视频转图片
import cv2

video_path = 'test.mp4'  # 视频地址
vid = cv2.VideoCapture(video_path)#打开视频
n = 0

while vid.isOpened():
    is_read, frame = vid.read()
    if is_read:
        cv2.imwrite(str(n) + '.jpg', frame)
        cv2.waitKey(2)#输出图片
    else:
        break

  如果测试使用的视频太长会导致程序会运行很久,我测试用的视频只有6s,却提取出了100多张图片。所以在测试的时候可以加一些条件,比如每10帧截取一次图片 等。这样可以提高调试效率。

  在后面数字识别的时候我发现识别结果的准确率很低,查了一些资料并进行了一些 测试后,我发现将图片变成黑白的可以很大的提高识别精度。这里使用到了 pillow 库。至此还剩一个问题,opencv 读出来的是 opencv 的图片格式,pillow 库使用 的是 img 格式,两种格式并不一样,所以这里需要小小的转换一下。以下是将 opencv 读取出的图片变成灰度图片并保存的代码。

#提取视频图片并保存为黑白图片
import cv2
import numpy
from PIL import Image

video_path = 'test_2.mp4'  # 视频地址

vid = cv2.VideoCapture(video_path)#打开视频
is_read, frame = vid.read()

if is_read:

    image_opencv = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
    image_org = Image.fromarray(image_opencv)
    image_org = image_org.convert('L')
    image_org.save('image_gray.jpg')#保存

    #以下代码是把上面的四行简写成两行了,最终程序这样写看起来会简洁些
    #image_org = Image.fromarray(cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)).convert('L')
    #image_org.save('org.jpg')

print("原图片尺寸为:\n" , image_org.size)

   这里我只保存了第一张的截图。图片效果如下。

视频的第一张灰度截图

  在后续的识别中还遇到了这样一个问题,代码会把其他不需要的数字识别出来,比如上图的设备型号 E5071C 等等。这样就导致后面数据不好处理。考虑到拍摄视频的时候手机是固定不动的,视频中需要识别的数据位置基本不会改变。所以我想直接手动截取需要的那一块图片,然后再去识别(方法有点笨 QAQ 我也没办法啦!)。因为之前已经变成 pillow 的 img 格式了,就直接使用 crop() 方法进行切割吧。

  具体使用方法是这样的:因为截取的是一个矩形区域,只要确定左上角和右下角的两个点的坐标,就能确定这个矩形区域的位置。在 crop(x1,y1,x2,y2) 中,这是两个点的坐标,第一个是左上角的点,第二个是右下角的点。使用的时候自己观察一下大概要截取哪一部分的图片,修改这两个点的坐标值就可以了。

  于是我就写了一个小工具来确定这两个坐标值。我将原尺寸的图片和截取的图片都保存下来,这样就可以直接观察截取的区间对不对了。这里还用到了下一部分的识别模块,等下就讲,那一句可以先注释掉。只需要运行下面的代码,看看截取的区间是否合适并且程序是否能识别就可以了。如果可以正确识别,我们就得到了这个合适的区间。

#确定区间的小工具
import cv2
import pytesseract
import numpy
from PIL import Image

name_of_result_file = 'result'#保存截图结果的图片文件名,可修改
name_of_frame_file = 'frame'#保存截图结果的图片文件名,可修改

box = (260, 880, 560, 1450)#数据,根据实际情况修改
result = ''#保存结果的字符串

video_path = 'test.mp4'  # 视频地址
vid = cv2.VideoCapture(video_path)#打开视频

is_read, frame = vid.read()
if is_read:

    image_org = Image.fromarray(cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)).convert('L')
    image_org.save('img_org.jpg')#原尺寸的图片

    region = image_org.crop(box)#截取左边的数字

   region.save('crop.jpg')
    result = pytesseract.image_to_string(region)#识别图片

print(result)

  这个区间不太好确定,需要多试几次,如下图所示就得到了可使用的区间了。

 识别结果

 截取区间

  至此图片处理部分就结束了。手动截取图片区间的时候需要注意,区间不能太小,否则什么都识别不出来,具体原因我也不清楚。我多次测试发现这个区间并不好找,我觉得主要原因还是原视频的清晰度不够,导致截取出来的图片很糊。我自己看起来都和马赛克一样,怎么让程序处理呢。如果视频比较清楚,那这个区间应当是很好找的。

转载请注明出处: https://www.cnblogs.com/mysteriouspavilion/articles/15389927.html


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM