日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

计算机视觉:数据预处理-图像增广方法

發布時間:2024/10/8 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 计算机视觉:数据预处理-图像增广方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

計算機視覺:數據預處理-圖像增廣方法

  • 數據預處理
    • 隨機改變亮暗、對比度和顏色等
    • 隨機填充
    • 隨機裁剪
    • 隨機縮放
    • 隨機翻轉
    • 隨機打亂真實框排列順序
    • 圖像增廣方法匯總
  • 批量數據讀取與加速

數據預處理

在計算機視覺中,通常會對圖像做一些隨機的變化,產生相似但又不完全相同的樣本。主要作用是擴大訓練數據集,抑制過擬合,提升模型的泛化能力,常用的方法見下面的程序。




隨機改變亮暗、對比度和顏色等

import numpy as np import cv2 from PIL import Image, ImageEnhance import random# 隨機改變亮暗、對比度和顏色等 def random_distort(img):# 隨機改變亮度def random_brightness(img, lower=0.5, upper=1.5):e = np.random.uniform(lower, upper)return ImageEnhance.Brightness(img).enhance(e)# 隨機改變對比度def random_contrast(img, lower=0.5, upper=1.5):e = np.random.uniform(lower, upper)return ImageEnhance.Contrast(img).enhance(e)# 隨機改變顏色def random_color(img, lower=0.5, upper=1.5):e = np.random.uniform(lower, upper)return ImageEnhance.Color(img).enhance(e)ops = [random_brightness, random_contrast, random_color]np.random.shuffle(ops)img = Image.fromarray(img)img = ops[0](img)img = ops[1](img)img = ops[2](img)img = np.asarray(img)return img

隨機填充

# 隨機填充 def random_expand(img,gtboxes,max_ratio=4.,fill=None,keep_ratio=True,thresh=0.5):if random.random() > thresh:return img, gtboxesif max_ratio < 1.0:return img, gtboxesh, w, c = img.shaperatio_x = random.uniform(1, max_ratio)if keep_ratio:ratio_y = ratio_xelse:ratio_y = random.uniform(1, max_ratio)oh = int(h * ratio_y)ow = int(w * ratio_x)off_x = random.randint(0, ow - w)off_y = random.randint(0, oh - h)out_img = np.zeros((oh, ow, c))if fill and len(fill) == c:for i in range(c):out_img[:, :, i] = fill[i] * 255.0out_img[off_y:off_y + h, off_x:off_x + w, :] = imggtboxes[:, 0] = ((gtboxes[:, 0] * w) + off_x) / float(ow)gtboxes[:, 1] = ((gtboxes[:, 1] * h) + off_y) / float(oh)gtboxes[:, 2] = gtboxes[:, 2] / ratio_xgtboxes[:, 3] = gtboxes[:, 3] / ratio_yreturn out_img.astype('uint8'), gtboxes

隨機裁剪

隨機裁剪之前需要先定義兩個函數,multi_box_iou_xywh和box_crop這兩個函數將被保存在box_utils.py文件中。

import numpy as npdef multi_box_iou_xywh(box1, box2):"""In this case, box1 or box2 can contain multi boxes.Only two cases can be processed in this method:1, box1 and box2 have the same shape, box1.shape == box2.shape2, either box1 or box2 contains only one box, len(box1) == 1 or len(box2) == 1If the shape of box1 and box2 does not match, and both of them contain multi boxes, it will be wrong."""assert box1.shape[-1] == 4, "Box1 shape[-1] should be 4."assert box2.shape[-1] == 4, "Box2 shape[-1] should be 4."b1_x1, b1_x2 = box1[:, 0] - box1[:, 2] / 2, box1[:, 0] + box1[:, 2] / 2b1_y1, b1_y2 = box1[:, 1] - box1[:, 3] / 2, box1[:, 1] + box1[:, 3] / 2b2_x1, b2_x2 = box2[:, 0] - box2[:, 2] / 2, box2[:, 0] + box2[:, 2] / 2b2_y1, b2_y2 = box2[:, 1] - box2[:, 3] / 2, box2[:, 1] + box2[:, 3] / 2inter_x1 = np.maximum(b1_x1, b2_x1)inter_x2 = np.minimum(b1_x2, b2_x2)inter_y1 = np.maximum(b1_y1, b2_y1)inter_y2 = np.minimum(b1_y2, b2_y2)inter_w = inter_x2 - inter_x1inter_h = inter_y2 - inter_y1inter_w = np.clip(inter_w, a_min=0., a_max=None)inter_h = np.clip(inter_h, a_min=0., a_max=None)inter_area = inter_w * inter_hb1_area = (b1_x2 - b1_x1) * (b1_y2 - b1_y1)b2_area = (b2_x2 - b2_x1) * (b2_y2 - b2_y1)return inter_area / (b1_area + b2_area - inter_area)def box_crop(boxes, labels, crop, img_shape):x, y, w, h = map(float, crop)im_w, im_h = map(float, img_shape)boxes = boxes.copy()boxes[:, 0], boxes[:, 2] = (boxes[:, 0] - boxes[:, 2] / 2) * im_w, (boxes[:, 0] + boxes[:, 2] / 2) * im_wboxes[:, 1], boxes[:, 3] = (boxes[:, 1] - boxes[:, 3] / 2) * im_h, (boxes[:, 1] + boxes[:, 3] / 2) * im_hcrop_box = np.array([x, y, x + w, y + h])centers = (boxes[:, :2] + boxes[:, 2:]) / 2.0mask = np.logical_and(crop_box[:2] <= centers, centers <= crop_box[2:]).all(axis=1)boxes[:, :2] = np.maximum(boxes[:, :2], crop_box[:2])boxes[:, 2:] = np.minimum(boxes[:, 2:], crop_box[2:])boxes[:, :2] -= crop_box[:2]boxes[:, 2:] -= crop_box[:2]mask = np.logical_and(mask, (boxes[:, :2] < boxes[:, 2:]).all(axis=1))boxes = boxes * np.expand_dims(mask.astype('float32'), axis=1)labels = labels * mask.astype('float32')boxes[:, 0], boxes[:, 2] = (boxes[:, 0] + boxes[:, 2]) / 2 / w, (boxes[:, 2] - boxes[:, 0]) / wboxes[:, 1], boxes[:, 3] = (boxes[:, 1] + boxes[:, 3]) / 2 / h, (boxes[:, 3] - boxes[:, 1]) / hreturn boxes, labels, mask.sum() # 隨機裁剪 def random_crop(img,boxes,labels,scales=[0.3, 1.0],max_ratio=2.0,constraints=None,max_trial=50):if len(boxes) == 0:return img, boxesif not constraints:constraints = [(0.1, 1.0), (0.3, 1.0), (0.5, 1.0), (0.7, 1.0),(0.9, 1.0), (0.0, 1.0)]img = Image.fromarray(img)w, h = img.sizecrops = [(0, 0, w, h)]for min_iou, max_iou in constraints:for _ in range(max_trial):scale = random.uniform(scales[0], scales[1])aspect_ratio = random.uniform(max(1 / max_ratio, scale * scale), \min(max_ratio, 1 / scale / scale))crop_h = int(h * scale / np.sqrt(aspect_ratio))crop_w = int(w * scale * np.sqrt(aspect_ratio))crop_x = random.randrange(w - crop_w)crop_y = random.randrange(h - crop_h)crop_box = np.array([[(crop_x + crop_w / 2.0) / w,(crop_y + crop_h / 2.0) / h,crop_w / float(w), crop_h / float(h)]])iou = multi_box_iou_xywh(crop_box, boxes)if min_iou <= iou.min() and max_iou >= iou.max():crops.append((crop_x, crop_y, crop_w, crop_h))breakwhile crops:crop = crops.pop(np.random.randint(0, len(crops)))crop_boxes, crop_labels, box_num = box_crop(boxes, labels, crop, (w, h))if box_num < 1:continueimg = img.crop((crop[0], crop[1], crop[0] + crop[2],crop[1] + crop[3])).resize(img.size, Image.LANCZOS)img = np.asarray(img)return img, crop_boxes, crop_labelsimg = np.asarray(img)return img, boxes, labels

隨機縮放

# 隨機縮放 def random_interp(img, size, interp=None):interp_method = [cv2.INTER_NEAREST,cv2.INTER_LINEAR,cv2.INTER_AREA,cv2.INTER_CUBIC,cv2.INTER_LANCZOS4,]if not interp or interp not in interp_method:interp = interp_method[random.randint(0, len(interp_method) - 1)]h, w, _ = img.shapeim_scale_x = size / float(w)im_scale_y = size / float(h)img = cv2.resize(img, None, None, fx=im_scale_x, fy=im_scale_y, interpolation=interp)return img

隨機翻轉

# 隨機翻轉 def random_flip(img, gtboxes, thresh=0.5):if random.random() > thresh:img = img[:, ::-1, :]gtboxes[:, 0] = 1.0 - gtboxes[:, 0]return img, gtboxes

隨機打亂真實框排列順序

# 隨機打亂真實框排列順序 def shuffle_gtbox(gtbox, gtlabel):gt = np.concatenate([gtbox, gtlabel[:, np.newaxis]], axis=1)idx = np.arange(gt.shape[0])np.random.shuffle(idx)gt = gt[idx, :]return gt[:, :4], gt[:, 4]

圖像增廣方法匯總

# 圖像增廣方法匯總 def image_augment(img, gtboxes, gtlabels, size, means=None):# 隨機改變亮暗、對比度和顏色等img = random_distort(img)# 隨機填充img, gtboxes = random_expand(img, gtboxes, fill=means)# 隨機裁剪img, gtboxes, gtlabels, = random_crop(img, gtboxes, gtlabels)# 隨機縮放img = random_interp(img, size)# 隨機翻轉img, gtboxes = random_flip(img, gtboxes)# 隨機打亂真實框排列順序gtboxes, gtlabels = shuffle_gtbox(gtboxes, gtlabels)return img.astype('float32'), gtboxes.astype('float32'), gtlabels.astype('int32')

這里得到的img數據數值需要調整,需要除以255,并且減去均值和方差,再將維度從[H, W, C]調整為[C, H, W]。

img, gt_boxes, gt_labels, scales = get_img_data_from_file(record) size = 512 img, gt_boxes, gt_labels = image_augment(img, gt_boxes, gt_labels, size) mean = [0.485, 0.456, 0.406] std = [0.229, 0.224, 0.225] mean = np.array(mean).reshape((1, 1, -1)) std = np.array(std).reshape((1, 1, -1)) img = (img / 255.0 - mean) / std img = img.astype('float32').transpose((2, 0, 1)) img

將上面的過程整理成一個get_img_data函數。

def get_img_data(record, size=640):img, gt_boxes, gt_labels, scales = get_img_data_from_file(record)img, gt_boxes, gt_labels = image_augment(img, gt_boxes, gt_labels, size)mean = [0.485, 0.456, 0.406]std = [0.229, 0.224, 0.225]mean = np.array(mean).reshape((1, 1, -1))std = np.array(std).reshape((1, 1, -1))img = (img / 255.0 - mean) / stdimg = img.astype('float32').transpose((2, 0, 1))return img, gt_boxes, gt_labels, scales TRAINDIR = '/home/aistudio/work/insects/train' TESTDIR = '/home/aistudio/work/insects/test' VALIDDIR = '/home/aistudio/work/insects/val' cname2cid = get_insect_names() records = get_annotations(cname2cid, TRAINDIR)record = records[0] img, gt_boxes, gt_labels, scales = get_img_data(record, size=480) img.shape (3, 480, 480) gt_boxes.shape (50, 4) gt_labels array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,0, 4, 0, 0, 0, 0], dtype=int32) scales (1244.0, 1244.0)

批量數據讀取與加速




下面的程序展示了如何讀取一張圖片的數據并加速,下面的代碼實現了批量數據讀取。

# 獲取一個批次內樣本隨機縮放的尺寸 def get_img_size(mode):if (mode == 'train') or (mode == 'valid'):inds = np.array([0,1,2,3,4,5,6,7,8,9])ii = np.random.choice(inds)img_size = 320 + ii * 32else:img_size = 608return img_size# 將 list形式的batch數據 轉化成多個array構成的tuple def make_array(batch_data):img_array = np.array([item[0] for item in batch_data], dtype = 'float32')gt_box_array = np.array([item[1] for item in batch_data], dtype = 'float32')gt_labels_array = np.array([item[2] for item in batch_data], dtype = 'int32')img_scale = np.array([item[3] for item in batch_data], dtype='int32')return img_array, gt_box_array, gt_labels_array, img_scale# 批量讀取數據,同一批次內圖像的尺寸大小必須是一樣的, # 不同批次之間的大小是隨機的, # 由上面定義的get_img_size函數產生 def data_loader(datadir, batch_size= 10, mode='train'):cname2cid = get_insect_names()records = get_annotations(cname2cid, datadir)def reader():if mode == 'train':np.random.shuffle(records)batch_data = []img_size = get_img_size(mode)for record in records:#print(record)img, gt_bbox, gt_labels, im_shape = get_img_data(record, size=img_size)batch_data.append((img, gt_bbox, gt_labels, im_shape))if len(batch_data) == batch_size:yield make_array(batch_data)batch_data = []img_size = get_img_size(mode)if len(batch_data) > 0:yield make_array(batch_data)return reader d = data_loader('/home/aistudio/work/insects/train', batch_size=2, mode='train') img, gt_boxes, gt_labels, im_shape = next(d()) img.shape, gt_boxes.shape, gt_labels.shape, im_shape.shape ((2, 3, 352, 352), (2, 50, 4), (2, 50), (2, 2))

由于數據預處理耗時較長,可能會成為網絡訓練速度的瓶頸,所以需要對預處理部分進行優化。通過使用飛槳提供的API paddle.reader.xmap_readers可以開啟多線程讀取數據,具體實現代碼如下。

import functools import paddle# 使用paddle.reader.xmap_readers實現多線程讀取數據 def multithread_loader(datadir, batch_size= 10, mode='train'):cname2cid = get_insect_names()records = get_annotations(cname2cid, datadir)def reader():if mode == 'train':np.random.shuffle(records)img_size = get_img_size(mode)batch_data = []for record in records:batch_data.append((record, img_size))if len(batch_data) == batch_size:yield batch_databatch_data = []img_size = get_img_size(mode)if len(batch_data) > 0:yield batch_datadef get_data(samples):batch_data = []for sample in samples:record = sample[0]img_size = sample[1]img, gt_bbox, gt_labels, im_shape = get_img_data(record, size=img_size)batch_data.append((img, gt_bbox, gt_labels, im_shape))return make_array(batch_data)mapper = functools.partial(get_data, )return paddle.reader.xmap_readers(mapper, reader, 8, 10) d = multithread_loader('/home/aistudio/work/insects/train', batch_size=2, mode='train') img, gt_boxes, gt_labels, im_shape = next(d()) img.shape, gt_boxes.shape, gt_labels.shape, im_shape.shape ((2, 3, 320, 320), (2, 50, 4), (2, 50), (2, 2))

至此,我們完成了如何查看數據集中的數據、提取數據標注信息、從文件讀取圖像和標注數據、圖像增廣、批量讀取和加速等過程,通過multithread_loader可以返回img, gt_boxes, gt_labels, im_shape等數據,接下來就可以將它們輸入到神經網絡,應用到具體算法上了。

在開始具體的算法講解之前,先補充一下讀取測試數據的代碼。測試數據沒有標注信息,也不需要做圖像增廣,代碼如下所示。

# 測試數據讀取# 將 list形式的batch數據 轉化成多個array構成的tuple def make_test_array(batch_data):img_name_array = np.array([item[0] for item in batch_data])img_data_array = np.array([item[1] for item in batch_data], dtype = 'float32')img_scale_array = np.array([item[2] for item in batch_data], dtype='int32')return img_name_array, img_data_array, img_scale_array# 測試數據讀取 def test_data_loader(datadir, batch_size= 10, test_image_size=608, mode='test'):"""加載測試用的圖片,測試數據沒有groundtruth標簽"""image_names = os.listdir(datadir)def reader():batch_data = []img_size = test_image_sizefor image_name in image_names:file_path = os.path.join(datadir, image_name)img = cv2.imread(file_path)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)H = img.shape[0]W = img.shape[1]img = cv2.resize(img, (img_size, img_size))mean = [0.485, 0.456, 0.406]std = [0.229, 0.224, 0.225]mean = np.array(mean).reshape((1, 1, -1))std = np.array(std).reshape((1, 1, -1))out_img = (img / 255.0 - mean) / stdout_img = out_img.astype('float32').transpose((2, 0, 1))img = out_img #np.transpose(out_img, (2,0,1))im_shape = [H, W]batch_data.append((image_name.split('.')[0], img, im_shape))if len(batch_data) == batch_size:yield make_test_array(batch_data)batch_data = []if len(batch_data) > 0:yield make_test_array(batch_data)return reader

總結

以上是生活随笔為你收集整理的计算机视觉:数据预处理-图像增广方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。