Opencv4学习记录(二)深度学习中图片【数据集的扩充】方法,python多进程通信问题记录

数据集

首先是我们这篇文章的核心内容:数据集扩充
在进行深度学习等相关的图像数据处理时,往往我们需要通过大量的数据集来进行训练。公开数据集的数据可以较好的对算法进行评估,得到一个比较客观的对算法的评价。但是更多时候在算法的应用上来说公开的数据集很难满足我们对于特定场景下的任务需求,特定的任务目标要求我们只识别几类我们关心的图像目标,比如果工业流水线上的缺陷检测,要检测的缺陷就是特定的一个目标。在比如制作移动机器人实现对特定物体的采集回收和放置,那个采集回收和放置的对象就是我们关心的检测目标,这往往是我们不能从公开数据集里找的,所以自建数据集的需求就出现了

数据集的制作

数据集的制作比较简单,但是也并不是没有任何要求。
从简单来说拍摄数据集就是要求我们尽可能全面的采集对象可能出出现在图像中的所有情况。但往往在实际情况中比较难以直接采集到丰富全面的图像数据,这就应运而生了数据集的扩充需求,通过对已有的数据集图像进行旋转,对称,仿射变换等操作批量的扩充已有的数据集。

数据集图像采集

#coding:utf-8
import cv2
cap = cv2.VideoCapture(0)#创建一个 VideoCapture 对象

flag = 1 #设置一个标志,用来输出视频信息
num = 1 #递增,用来保存文件名
while(cap.isOpened()):#循环读取每一帧
    ret_flag, Vshow = cap.read() #返回两个参数,第一个是bool是否正常打开,第二个是照片数组,如果只设置一个则变成一个tumple包含bool和图片
    cv2.imshow("Capture_Video",Vshow)  #窗口显示,显示名为 Capture_Test
    k = cv2.waitKey(1) & 0xFF #每帧数据延时 1ms,延时不能为 0,否则读取的结果会是静态帧
    if k == ord('s'):  #若检测到按键 ‘s’,打印字符串
        cv2.imwrite("mage/"+ str(num) + ".jpg", Vshow)
        print("success to save {}.jpg, image size w:{} y:{}".format(str(num), cap.get(3), cap.get(4)))
        print("-------------------------")
        num += 1
    elif k == ord('q'): #若检测到按键 ‘q’,退出import 
        break
cap.release() #释放摄像头
cv2.destroyAllWindows()#删除建立的全部窗口

扩充数据集

import os
import cv2

# =============================================
#               数据集图像扩充
# =============================================

path = '\image'
savepath = '\JPGImages'
imagewight = 480	# 这两个参数改为自己需要的长和宽
imagehight = 480
imagerow = 30
print("image read from {}, save in {}".format(path, savepath))

path_list = os.listdir(path)

imagenumber = 141
for filename in path_list:
    image = cv2.imread(os.path.join(path,filename), 1)

    # =============================================
    #               固定尺寸缩放
    # =============================================
    res = cv2.resize(image, (imagewight, imagehight), interpolation=cv2.INTER_LINEAR)
    imagename = str(imagenumber)+'.jpg'
    cv2.imwrite(os.path.join(savepath,imagename), res)
    imagenumber += 1'

    # =============================================
    #              上下翻转
    # =============================================
    dst1 = cv2.flip(res, 0)
    imagename = str(imagenumber) + '.jpg'
    cv2.imwrite(os.path.join(savepath, imagename), dst1)
    imagenumber += 1

    # =============================================
    #               左右对称翻转
    # =============================================
    dst3 = cv2.flip(res, -1)
    imagename = str(imagenumber) + '.jpg'
    cv2.imwrite(os.path.join(savepath, imagename), dst3)
    imagenumber += 1

    # =============================================
    #               仿射旋转
    # =============================================
    # 这里的第一个参数为旋转中心,第二个为旋转角度,第三个为旋转后的缩放因子
    # 可以通过设置旋转中心,缩放因子以及窗口大小来防止旋转后超出边界的问题
    M = cv2.getRotationMatrix2D((imagewight/2 , imagehight/2), imagerow, 1.2)
    wap = cv2.warpAffine(res, M, (imagewight, imagehight), borderValue=(255, 255, 255))  # M为上面的旋转矩阵
    imagename = str(imagenumber) + '.jpg'
    cv2.imwrite(os.path.join(savepath, imagename), wap)
    if imagerow < 320:
        imagerow += 30
    else:
        imagerow = 30
    imagenumber += 1

print("all image secussful!! image save in {}".format(savepath))
cv2.waitKey()
cv2.destroyAllWindows()

问题记录

在python中使用多进程,多进程间通信需要注意

在学习进行一些AIoT的项目的过程中,不能只是简单的把所有的代码放在一个主函数里面if __name__=="main":里面跑,那样的话代码的执行效率非常低。但我相信初学的时候应该有一部分电子人不是计算机专业出身,大概率是只学了c语言做嵌入式,对python和c++有些头大。其实这是废话了(手动狗头)。说回正话,我们需要通过python多进程编程来利用好多核芯片的性能,加速我们的程序运行效率,在c++中也可使使用多线程并发,但python的多线程行为解释器的设计规则导致它不能利用多核心运行。当然如果是MicorePython用户就可以跳过思考多进程啥的了
在实际的开发中我遇到的问题是这样的:
定义了两个子进程,他们之间是通过管道Pipe进行通信的,其中一个子进程进行串口的数据输出,编程时我发现如果串口无法正确发出数据的时候会导致整个程序卡死,并且没有报错信息。原因是串口作为一个IO操作,本身需要一定的耗时,而且在串口发送完一帧数据以后,通常需要延时一段时间,所以串口子进程的执行速度远远低于图像处理子进程的速度,导致图像处理完之后的大量的数据拥塞无法发送出去,最后导致了程序的卡死

解决方法

可以使用消息队列,将消息的最大数目控制在合适范围内,保证读取进程读取的消息不过时,也可以保证一定的传输数据缓冲区。
也可以使用共享内存的方法,这个方法是最保险的错做,数据始终在内存区存留,何时写与读并不相互干扰。但共享内存的设置比较麻烦,用哪个方法就看时间和自己选了。

猜你喜欢

转载自blog.csdn.net/weixin_47407066/article/details/124534952