Filter by دسته‌ها
chatGTP
ابزارهای هوش مصنوعی
اخبار
گزارش
تیتر یک
چندرسانه ای
آموزش علوم داده
اینفوگرافیک
پادکست
ویدیو
دانش روز
آموزش‌های پایه‌ای هوش مصنوعی
اصول هوش مصنوعی
یادگیری بدون نظارت
یادگیری تقویتی
یادگیری عمیق
یادگیری نیمه نظارتی
آموزش‌های پیشرفته هوش مصنوعی
بینایی ماشین
پردازش زبان طبیعی
پردازش گفتار
چالش‌های عملیاتی
داده کاوی و بیگ دیتا
رایانش ابری و HPC
سیستم‌‌های امبدد
علوم شناختی
دیتاست
رویدادها
جیتکس
کاربردهای هوش مصنوعی
کتابخانه
اشخاص
شرکت‌های هوش مصنوعی
محصولات و مدل‌های هوش مصنوعی
مفاهیم
کسب‌و‌کار
تحلیل بازارهای هوش مصنوعی
کارآفرینی
هوش مصنوعی در ایران
هوش مصنوعی در جهان
مقاله
 داده افزایی تصویری و چگونگی انجام آن در کتابخانه‌ی OpenCV

داده افزایی تصویری و چگونگی انجام آن در کتابخانه‌ی OpenCV

زمان مطالعه: 4 دقیقه

چند روز پیش در حال نوشتن مقاله‌­ای بودم که به استفاده از فضای رنگی Color spaces متفاوت به عنوان ورودی شبکه های عصبی پیچشی (CNN) می‌پرداخت و به همین دلیل لازم بود از یک مولد داده برای داده افزایی تصویری استفاده کنم؛ چون نمی‌توانستم از مولد داده داخلی تنسورفلو بدین منظور استفاده کنم. بعد از جست‌وجو، چندین مقاله‌ی مرتبط پیدا کردم، اما هیچ کدام آن­ها به طور کامل این موضوع را پوشش نداده بودند؛ بنابراین تصمیم گرفتم شخصاً این کار را انجام دهم.

در صورت تمایل به آشنایی با نحوه‌ی کار هر کدام از این توابع می‌­توانید به این مقاله مراجعه کنید. برای مصورسازی از تصویر طاق پیروزی (تصویر اصلی آن­‌را پایین مشاهده می‌­کنید) استفاده خواهیم کرد.

داده افزایی تصویری-تصویر آزمایشی
تصویر آزمایشی

جابجایی افقی

در اولین بخش از بحث داده افزایی تصویری به جابجایی افقی خواهیم پرداخت. جابجایی یا برگردان translation افقی به جابه‌جا کردن یک تصویر به چپ یا راست بر اساس یک نسبت گفته می­‌شود؛ این نسبت حداکثر میزان جابجایی را مشخص می­‌کند. به منظور تنظیم مجدد تصویر و برگشت به ابعاد اصلی، Keras به صورت پیش‌­فرض از یک مقدار ورودی به نام nearest استفاده می‌کند که قسمت‌های از دست رفته عکس را پر می‌کند.

داده افزایی تصویری-نتیجه‌ی حالت تمام‌صفحه nearest
نتیجه‌ی حالت تمام‌صفحه nearest

این عمل باعث می‌­شود قسمتی از تصویر بلا­استفاده باقی بماند، به همین دلیل تصویر را به اندازه‌ی اصلی باز می­‌گردانم. پس آموختیم که برای انجام این کار باید یک عدد تصادفی تولید کنیم و سپس تصویر را از طریق شاخص­‌گذاری indexing به سمت چپ یا راست جابجا کنیم.

import cv2
import random
img = cv2.imread('arc_de_triomphe.jpg')

def fill(img, h, w):
    img = cv2.resize(img, (h, w), cv2.INTER_CUBIC)
    return img
        
def horizontal_shift(img, ratio=0.0):
    if ratio > 1 or ratio < 0:
        print('Value should be less than 1 and greater than 0')
        return img
    ratio = random.uniform(-ratio, ratio)
    h, w = img.shape[:2]
    to_shift = w*ratio
    if ratio > 0:
        img = img[:, :int(w-to_shift), :]
    if ratio < 0:
        img = img[:, int(-1*to_shift):, :]
    img = fill(img, h, w)
    return img

img = horizontal_shift(img, 0.7)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
داده افزایی تصویری-جابجایی افقی
جابجایی افقی

جابجایی عمودی

دیگر بحثی که برای داده افزایی تصویری از اهمیت زیادی برخوردار است، جابجایی عمودی است. اجرای جابجایی عمودی تفاوت چندانی با نحوه­‌ی جابجایی افقی ندارد.

import cv2
import random

img = cv2.imread('arc_de_triomphe.jpg')

def fill(img, h, w):
    img = cv2.resize(img, (h, w), cv2.INTER_CUBIC)
    return img

def vertical_shift(img, ratio=0.0):
    if ratio > 1 or ratio < 0:
        print('Value should be less than 1 and greater than 0')
        return img
    ratio = random.uniform(-ratio, ratio)
    h, w = img.shape[:2]
    to_shift = h*ratio
    if ratio > 0:
        img = img[:int(h-to_shift), :, :]
    if ratio < 0:
        img = img[int(-1*to_shift):, :, :]
    img = fill(img, h, w)
    return img

img = vertical_shift(img, 0.7)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
داده افزایی تصویری-جابجایی عمودی
جابجایی عمودی

روشنایی

روشنایی یکی از عوامل مهم در داده افزایی تصویری است. پیش­تر مقاله­‌ای در مورد فیلترهای مختلف (کارتونی، تابستانی، زمستانی و …) تصاویر نوشته بودم که تابع روشنایی را در بر می‌گرفت.

برای انجام این مسئله باید از فضای رنگی HSV استفاده کنیم. هرچه مقدار اشباع رنگ Value of saturation و ماتریس­‌های مقادیر Value matrices بالاتر باشد، روشنایی هم بیشتر خواهد بود. بنابراین به منظور افزایش روشنایی باید این مقادیر را در عددی بزرگ­تر از 1 و برای کاهش آن در عددی کوچک­تر از 1 ضرب کنیم. در کتابخانه‌ی تنسورفلو ابتدا یک بازه مشخص شده و سپس از درون این بازه یک مقدار به صورت تصادفی انتخاب می­‌گردد.

import cv2
import random
import numpy as np

img = cv2.imread('arc_de_triomphe.jpg')

def brightness(img, low, high):
    value = random.uniform(low, high)
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    hsv = np.array(hsv, dtype = np.float64)
    hsv[:,:,1] = hsv[:,:,1]*value
    hsv[:,:,1][hsv[:,:,1]>255]  = 255
    hsv[:,:,2] = hsv[:,:,2]*value 
    hsv[:,:,2][hsv[:,:,2]>255]  = 255
    hsv = np.array(hsv, dtype = np.uint8)
    img = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
    return img

img = brightness(img, 0.5, 3)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
داده افزایی تصویری-روشنایی
روشنایی

زوم

در کتابخانه‌ی تنسورفلو برای اجرای تابع زوم ابتدا یک بازه را در نظر گرفته و از درون آن مقادیری به صورت تصادفی انتخاب می‌کنیم. اگر این مقادیر از 1 کوچک­تر باشند، تصویر بزرگ­نمایی می‌­شود و اگر بزرگ­تر از 1 باشند، تصویر کوچک شده و سپس با nearest به ابعاد واقعی خود برمی‌گردد. با این حال، از آن‌جایی که می­‌خواهیم تصاویر را به اندازه­‌ی واقعی آن­ها برگردانیم، فقط مقادیر کمتر از 1 را انتخاب می­‌کنیم. برای نمونه مقدار 0.6 بدین معنی است که 60% از کل تصویرگرفته خواهد شد و سپس تصویر به ابعاد اصلی بر خواهد گشت.

import cv2
import random
img = cv2.imread('arc_de_triomphe.jpg')

def fill(img, h, w):
    img = cv2.resize(img, (h, w), cv2.INTER_CUBIC)
    return imgdef zoom(img, value):
    if value > 1 or value < 0:
        print('Value for zoom should be less than 1 and greater than 0')
        return img
    value = random.uniform(value, 1)
    h, w = img.shape[:2]
    h_taken = int(value*h)
    w_taken = int(value*w)
    h_start = random.randint(0, h-h_taken)
    w_start = random.randint(0, w-w_taken)
    img = img[h_start:h_start+h_taken, w_start:w_start+w_taken, :]
    img = fill(img, h, w)
    return imgimg = zoom(img, 0.5)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
داده افزایی تصویری-زوم
زوم

جابجایی کانالی

دیگر مورد لازم برای داده افزایی تصویری جابجایی کانالی است. برای اجرای جابجایی کانالی، یک مقدار را به صورت تصادفی از بازه‌ای معین انتخاب کرده و به همه­‌ی کانال­‌های تصویر اضافه می­‌کنیم. نتیجه تقریباً شبیه تابع روشنایی است:

import cv2
import random
import numpy as np

img = cv2.imread('arc_de_triomphe.jpg')

def channel_shift(img, value):
    value = int(random.uniform(-value, value))
    img = img + value
    img[:,:,:][img[:,:,:]>255]  = 255
    img[:,:,:][img[:,:,:]<0]  = 0
    img = img.astype(np.uint8)
    return img

img = channel_shift(img, 60)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
داده افزایی تصویری-جابجایی کانالی
جابجایی کانالی

چرخش افقی

برای اجرای این تابع چرخش افقی در مبحث داده افزایی تصویری به یک متغیر بولی Boolean variable نیاز داریم؛ این متغیر مشخص می­‌کند یک چرخش افقی انجام می‌شود یا خیر. یک تابع داخلی در OpenCV  (cv2.flip)  وجود دارد که صرفاً برای اجرای این عملیات مورد استفاده قرار می­‌گیرد.

import cv2
img = cv2.imread('arc_de_triomphe.jpg')
def horizontal_flip(img, flag):
    if flag:
        return cv2.flip(img, 1)
    else:
        return img

img = horizontal_flip(img, True)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
داده افزایی تصویری-چرخش افقی
چرخش افقی

چرخش عمودی

این تابع نیز همچون تابع چرخش افقی با استفاده از cv2.flip  برای داده افزایی تصویری انجام می­‌شود. اما آرگومانargument دوم آن باید 0 باشد.

import cv2img = cv2.imread('arc_de_triomphe.jpg')
def vertical_flip(img, flag):
    if flag:
        return cv2.flip(img, 0)
    else:
        return img

img = vertical_flip(img, True)
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
داده افزایی تصویری-چرخش عمودی
گردش عمودی

گردش

برای اجرای تابع گردش در بحث داده افزایی تصویری در OpenCV باید یک ماتریکس گردش ایجاد کنیم و سپس تبدیلات آفین Affine transformations را روی آن اعمال نماییم.

import cv2

img = cv2.imread('arc_de_triomphe.jpg')
def rotation(img, angle):
    angle = int(random.uniform(-angle, angle))
    h, w = img.shape[:2]
    M = cv2.getRotationMatrix2D((int(w/2), int(h/2)), angle, 1)
    img = cv2.warpAffine(img, M, (w, h))
    return img

img = rotation(img, 30)    
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
داده افزایی تصویری-گردش
گردش

تمام­‌صفحه

پیش­تر از حالت تمام­‌صفحه‌­ی nearest گفتیم و اشاره کردم که به جای استفاده از آن، اندازه­‌ی تصاویر را تغییر می­‌دهم. با این حال از آن­جایی که قصد دارم لیست کاملی را در این مقاله ارائه کرده باشم، نحوه­‌ی ساخت همه­‌ی حالت­‌های تمام­‌صفحه را (اعم از nearest) توضیح خواهم داد. متن پایین از مستندات تنسورفلو گرفته شده است:

fill_mode: One of {“constant”, “nearest”, “reflect” or “wrap”}. Default is ‘nearest’. Points outside the boundaries of the input are filled according to the given mode:

‘constant’: kkkkkkkk|abcd|kkkkkkkk (cval=k)

‘nearest’: aaaaaaaa|abcd|dddddddd

‘reflect’: abcddcba|abcd|dcbaabcd

‘wrap’: abcdabcd|abcd|abcdabcd

این موارد را با جابجایی افقی درست می‌­کنم. تابع cv2.copyMakeBorder  در تمام‌­صفحه کردن تصویر کاربرد دارد؛ این تابع آرگومان‌ها را به عنوان وضعیت بالا، پایین، چپ، راست و حالت تصویر در نظر می­‌گیرد. بالا، پایین، چپ و راست به اندازه­‌ی مرز تصویر اشاره دارند.

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('arc_de_triomphe.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

def fill_mode(img, left, right):
    nearest = cv2.copyMakeBorder(img, 0, 0, left, right, cv2.BORDER_REPLICATE)
    reflect = cv2.copyMakeBorder(img, 0, 0, left, right, cv2.BORDER_REFLECT)
    wrap = cv2.copyMakeBorder(img, 0, 0, left, right, cv2.BORDER_WRAP)
    constant= cv2.copyMakeBorder(img, 0, 0, left, right, cv2.BORDER_CONSTANT,value=(255, 0, 0))
    
    plt.subplot(221),plt.imshow(nearest,'gray'),plt.title('NEAREST'),plt.axis('off')
    plt.subplot(222),plt.imshow(reflect,'gray'),plt.title('REFLECT'),plt.axis('off')
    plt.subplot(223),plt.imshow(wrap,'gray'),plt.title('WRAP'),plt.axis('off')
    plt.subplot(224),plt.imshow(constant,'gray'),plt.title('CONSTANT'),plt.axis('off')

def horizontal_shift_mode(img, ratio):
    if ratio > 1 or ratio < 0:
        print('Value for horizontal shift should be less than 1 and greater than 0')
        return img
    ratio = random.uniform(-ratio, ratio)
    h, w = img.shape[:2]
    to_shift = int(w*ratio)
    if ratio > 0:
        img = img[:, :w-to_shift, :]
        fill_mode(img, to_shift, 0)
    if ratio < 0:
        img = img[:, -1*to_shift:, :]
        fill_mode(img, 0, -1*to_shift)horizontal_shift_mode(img, 0.8)
داده افزایی تصویری-حالت‌های تمام‌صفحه
حالت‌های تمام‌صفحه

 

در صورت تمایل به آشنایی با نحوه­‌ی ایجاد یک مولد دیتای ساختگی، به این مقاله مراجعه کنید.

میانگین امتیاز / 5. تعداد ارا :

مطالب پیشنهادی مرتبط

اشتراک در
اطلاع از
0 نظرات
بازخورد (Feedback) های اینلاین
مشاهده همه دیدگاه ها
[wpforms id="48325"]