opencv图像翻转与数据增强的细节

在opencv中有多个图像翻转函数应用到SSD和yolov3中的数据增强模块里,例如左右翻转,上下翻转,水平垂直翻转。在opencv里最常用的图像翻转函数是cv2.flip,其中有一个参数flipCode=1表示水平翻转,flipCode=0表示垂直翻转,flipCode=-1表示水平垂直翻转,而在yolov3中的数据增强模块里(参见https://github.com/ultralytics/yolov3/blob/master/utils/datasets.py里的LoadImagesAndLabels类的__getitem__函数),对图像做左右翻转和上下翻转用的函数分别是np.fliplr和np.flipud。现在,我们就来比较一下这两种图像翻转函数的区别,以一张银行卡作为实验数据,编写代码如下

import cv2
import numpy as np

if __name__ == '__main__':
    imgpath = 'CCB.jpg'

    srcimg = cv2.imread(imgpath)

    img1 = cv2.flip(srcimg,1)

    img2 = cv2.flip(srcimg, -1)

    img3 = cv2.flip(srcimg, 0)

    imglr = np.fliplr(srcimg)

    imgud = np.flipud(srcimg)

    cv2.imshow('srcimg', srcimg)
    cv2.imshow('img1', img1)
    cv2.imshow('img2', img2)
    cv2.imshow('img3', img3)
    cv2.imshow('imglr', imglr)
    cv2.imshow('imgud', imgud)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

运行结果如下,下面显示的分别是原图,cv2.flip的参数flipCode=1,-1,0这三种情况的结果,可以看到,在flipCode=1和0的翻转图片里的文字是反的,相当于是镜像文字,而flipCode=-1的翻转图片里的文字是正的

下面是np.fliplr和np.flipud的翻转结果,可以看到图片里的文字依然是反的

通常,在训练yolov3的时候,读取图片的同时要读取标注文件获得目标的边界框信息,如果对图片做翻转,那么目标边界框也需要做几何变换。接下来,我们探讨图片翻转后的边界框的几何变换,考虑cv2.flip的参数flipCode=1,-1,0这三种情况,编写代码如下

import cv2
import xml.etree.ElementTree as ET
import numpy as np

if __name__ == '__main__':
    imgpath = 'CCB.jpg'
    xmlpath = 'ccb.xml'

    srcimg = cv2.imread(imgpath)
    h, w = srcimg.shape[:2]
    boxs = []
    tree = ET.parse(xmlpath)
    root = tree.getroot()
    for obj in root.findall('object'):
        xmin = int(obj.find('bndbox/xmin').text)
        ymin = int(obj.find('bndbox/ymin').text)
        xmax = int(obj.find('bndbox/xmax').text)
        ymax = int(obj.find('bndbox/ymax').text)
        boxs.append((xmin, ymin, xmax, ymax, obj.find('name').text))

    drawimg = srcimg.copy()
    for i,box in enumerate(boxs):
        xmin, ymin, xmax, ymax, label = box
        cv2.rectangle(drawimg, (xmin, ymin), (xmax, ymax), (0, 0, 255), thickness=2)
        #cv2.putText(drawimg, label, (xmin, ymin + 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), thickness=1)

    img1 = cv2.transpose(srcimg)
    img1 = cv2.flip(img1,1)
    for i,box in enumerate(boxs):
        xmin, ymin, xmax, ymax, label = box
        xmin, ymin, xmax, ymax = h-ymin, xmin, h-ymax, xmax
        if xmin > xmax:
            xmin, xmax = xmax, xmin
        if ymin > ymax:
            ymin, ymax = ymax, ymin
        cv2.rectangle(img1, (xmin, ymin), (xmax, ymax), (0, 0, 255), thickness=2)
        #cv2.putText(img1, label, (xmin, ymin + 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), thickness=1)

    img2 = cv2.flip(srcimg, -1)
    for i,box in enumerate(boxs):
        xmin, ymin, xmax, ymax, label = box
        xmin, ymin, xmax, ymax = w-xmin, h-ymin, w-xmax, h-ymax
        if xmin > xmax:
            xmin, xmax = xmax, xmin
        if ymin > ymax:
            ymin, ymax = ymax, ymin
        cv2.rectangle(img2, (xmin, ymin), (xmax, ymax), (0, 0, 255), thickness=2)
        #cv2.putText(img2, label, (xmin, ymin + 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), thickness=1)

    img3 = cv2.transpose(srcimg)
    img3 = cv2.flip(img3, 0)
    for i, box in enumerate(boxs):
        xmin, ymin, xmax, ymax, label = box
        xmin, ymin, xmax, ymax = ymin, w-xmin, ymax, w-xmax
        if xmin > xmax:
            xmin, xmax = xmax, xmin
        if ymin > ymax:
            ymin, ymax = ymax, ymin
        cv2.rectangle(img3, (xmin, ymin), (xmax, ymax), (0, 0, 255), thickness=2)
        #cv2.putText(img3, label, (xmin, ymin + 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), thickness=1)

    cv2.namedWindow('srcimg', cv2.WINDOW_NORMAL)
    cv2.imshow('srcimg', drawimg)
    cv2.namedWindow('img1', cv2.WINDOW_NORMAL)
    cv2.imshow('img1', img1)
    cv2.namedWindow('img2', cv2.WINDOW_NORMAL)
    cv2.imshow('img2', img2)
    cv2.namedWindow('img3', cv2.WINDOW_NORMAL)
    cv2.imshow('img3', img3)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
读取图片和标注xml文件后,对原图做三种翻转,并且给图中的目标画矩形框,运行结果如下,

可以看到,对于flipCode=1和0这两种情况,在执行cv2.flip函数之前使用cv2.transpose函数,就能保证在翻转后的图片里的文字依然是正的。并且对于flipCode=1,0,-1这三种情况,在翻转后的目标边界框的计算公式也有区别,读者可以仔细推敲。通过这个实验,可以尝试把cv2.flip函数也加入到ssd或者yolov3的数据增强函数里,丰富数据增强的方法

猜你喜欢

转载自blog.csdn.net/nihate/article/details/106377554