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

فیلترهای فتوشاپ در OpenCV

فیلترهای عکس همیشه یکی از محبوب‌ترین و جالب‌ترین برنامه‌های پردازش عکس بوده و هستند. و چه برنامه‌ای بهتر از فتوشاپ برای طراحی فیلترهای عکس! در این نوشتار به فیلترهای فتوشاپ در OpenCV خواهیم پرداخت.

یکی از ویژگی‌های جالب فیلترهای فتوشاپ در OpenCV وجود trackbar ها هستند که می‌توان با آن‌ها شدت فیلترها را کنترل کرد و موجب می‌شود جلوه (effect) عالی و مناسبی بر روی عکس اجرا شود. فیلترهای فتوشاپ در OpenCV که در این مقاله اجرا خواهیم کرد، عبارتند از:

  • Brightness (روشنایی)
  • ۶۰’s TV )تلویزیون دهه ۶۰)
  • Emboss (برجسته کردن)
  • Duo-Tone (جلوه‌های رنگی دوتایی)
  • Sepia (رنگ سوبیایی)

۱- روشنایی

منظور از روشنایی شدت نور است. با استفاده از کانال رنگی HSV می‌توان روشنایی را در تصاویر دستکاری کرد. اگر خلاصه بخواهیم بگوییم دومین و سومین کانال رنگی HSV:

  • بُعد saturation مشابه رنگ‌های روشن مختلف است. بُعد Value ترکیبی از این رنگ‌ها با مقادیر مختلفی از رنگ‌های سیاه و سفید شباهت است.

معنای جمله فوق در خودِ جمله نهفته است و به ما نشان می‌دهد چرا استفاده از کانال رنگی HSV برای این مسئله گزینه‌ای عالی و فوق‌العاده است. همان‌گونه که در تصویر مقابل مشاهده می‌کنید همزمان با افزایش معیارهای Saturation و Value از چپ به راست، جلوه‌ها هم تغییر می‌کنند.

OpenCV
مقادیر HSV که در RGB نشان داده می‌شوند و مقادیر Saturation و Value از چپ به راست افزایش پیدا می‌کنند.

 

به تصویر بالا نگاه کنید. همزمان با این‌که مقادیر این معیارها را افزایش می‌دهیم، رنگ‌ها روشن‌تر می‌شوند. برای ویرایش روشنایی و روشن‌تر کردن تصویر، مقادیر Saturation و Value را افزایش دهید.

کد پایتون:

def brightness(img):
    cv2.namedWindow('image')
    cv2.createTrackbar('val', 'image', 100, 150, nothing)

    while True:
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        hsv = np.array(hsv, dtype=np.float64)
        val = cv2.getTrackbarPos('val', 'image')
        val = val/100 # dividing by 100 to get in range 0-1.5

        # scale pixel values up or down for channel 1(Saturation)
        hsv[:, :, 1] = hsv[:, :, 1] * val
        hsv[:, :, 1][hsv[:, :, 1] > 255] = 255 # setting values > 255 to 255.
        # scale pixel values up or down for channel 2(Value)
        hsv[:, :, 2] = hsv[:, :, 2] * val
        hsv[:, :, 2][hsv[:, :, 2] > 255] = 255 # setting values > 255 to 255.

        hsv = np.array(hsv, dtype=np.uint8)
        res = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)

        cv2.imshow("original", img)
        cv2.imshow('image', res)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cv2.destroyAllWindows()

کد C++:

#include <iostream>
#include <string>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace std;
using namespace cv;


void nothing(int x, void* data) {}

void brightness(Mat img) {
	

	namedWindow("image");
	int slider = 100;
	createTrackbar("val","image",&slider,150,nothing);
	Mat hsv;

	while (true) {
		cvtColor(img, hsv, COLOR_BGR2HSV);
		float val = getTrackbarPos("val","image");
		val=val/100.0;
		Mat channels[3];
		split(hsv,channels);
		Mat H = channels[0];
		H.convertTo(H,CV_32F);
		Mat S = channels[1];
		S.convertTo(S,CV_32F);
		Mat V = channels[2];
		V.convertTo(V,CV_32F);

		for (int i=0; i < H.size().height; i++){
			for (int j=0; j < H.size().width; j++){
	// scale pixel values up or down for channel 1(Saturation)
				S.at<float>(i,j) *= val;
				if (S.at<float>(i,j) > 255)
					S.at<float>(i,j) = 255;

	// scale pixel values up or down for channel 2(Value)
				V.at<float>(i,j) *= val;
				if (V.at<float>(i,j) > 255)
					V.at<float>(i,j) = 255;
			}
		}
		H.convertTo(H,CV_8U);
		S.convertTo(S,CV_8U);
		V.convertTo(V,CV_8U);

		vector<Mat> hsvChannels{H,S,V};
		Mat hsvNew;
    		merge(hsvChannels,hsvNew);

    		Mat res;
    		cvtColor(hsvNew,res,COLOR_HSV2BGR);

    		imshow("original",img);
    		imshow("image",res);

	    	if (waitKey(1) == 'q')
	    		break;
		}
	destroyAllWindows();
}

در کد فوق، تصویر را به یک فضای رنگی HSV تبدیل کردیم که نوع داده آن float.64 است. فقط به این دلیل تصویر را تبدیل می‌کنیم که مطمئن شویم حاصل ضرب دو عدد اعشاری در هم  خطایی نخواهد داشت. با اجرای تابع cv2.createTrackbar می‌توانیم track bar ایجاد کنیم.  با استفاده از track bar می‌توانیم مقدار سطوح روشنایی را کنترل کنیم. تابع track bar عدد اعشاری به دست نمی‌دهد. با این حال در این تابع از اعداد بزرگ استفاده می‌شود و این اعداد بر ۱۰۰ تقسیم می‌شوند.

نکته: این فرایند برای تمامی فیلترها یکسان است و می‌توان آن را بر روی سایر فیلترها اجرا کرد.

سپس مقدار به دست آمده در ماتریس‌ها ضرب می‌شود. در نتیجه سقف مجاز رقم  برابر با ۲۵۵ خواهد بود. در گام نهایی مجدداً ماتریس‌ها را به RGB و uint8 تبدیل می‌کنیم.

تماشای ویدیو از طریق آدرس زیر:

https://www.youtube.com/watch?v=H4JCtL_l4w8&feature=youtu.be

۲(تلویزیون دهه ۶۰)

خب من هیچ کدام از برنامه‌های تلویزیونی دهه ۶۰ را تماشا نکرده‌ام. ولی فکر می‌کنم برنامه‌های تلویزیونی آن زمان سیاه و سفید بودند و نویز و برفک داشته‌اند. البته من تنها کسی نیستم که این عقیده را دارم. نسخه موبایلی Adobe Photoshop هم حرف مرا تأئید می‌کند.

تلویزیون دهه 60
اجرای فیلتر ۶۰’s TV بر روی عکس در Adobe Photoshop

 

ساده‌ترین راه اضافه کردن نویز  salt and pepper به عکس است. اگر این نویز را بر روی عکس اعمال کنیم، پیکسل‌های عکس تغییر می‌کنند. پس از آن می‌توانیم یک مقدار به پیکسل اضافه کنیم و یا یک مقدار از آن کم کنیم (که البته یک مقدار خاص و مشخص خواهد بود). این مقدار مشتقی از مقدار اصلی خواهد بود.

کد پایتون:

def tv_60(img):
    cv2.namedWindow('image')
    cv2.createTrackbar('val', 'image', 0, 255, nothing)
    cv2.createTrackbar('threshold', 'image', 0, 100, nothing)

    while True:
        height, width = img.shape[:2]
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        thresh = cv2.getTrackbarPos('threshold', 'image')
        val = cv2.getTrackbarPos('val', 'image')
        for i in range(height):
            for j in range(width):
                if np.random.randint(100) <= thresh:
                    if np.random.randint(2) == 0:
                        gray[i, j] = min(gray[i, j] + np.random.randint(0, val+1), 255) # adding noise to image and setting values > 255 to 255. 
                    else:
                        gray[i, j] = max(gray[i, j] - np.random.randint(0, val+1), 0) # subtracting noise to image and setting values < 0 to 0.

        cv2.imshow('Original', img)
        cv2.imshow('image', gray)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cv2.destroyAllWindows()

کد C++:

void tv_60(Mat img) {
	
	namedWindow("image");
	int slider = 0;
	int slider2 = 0;
	createTrackbar("val","image",&slider,255,nothing);
	createTrackbar("threshold","image",&slider2,100,nothing);

	while (true) {
		int height = img.size().height;
		int width = img.size().width;
		Mat gray;
		cvtColor(img, gray, COLOR_BGR2GRAY);
		float thresh = getTrackbarPos("threshold","image");
		float val = getTrackbarPos("val","image");

		for (int i=0; i < height; i++){
			for (int j=0; j < width; j++){
				if (rand()%100 <= thresh){
					if (rand()%2 == 0)
						gray.at<uchar>(i,j) = std::min(gray.at<uchar>(i,j) + rand()%((int)val+1), 255);
					else
						gray.at<uchar>(i,j) = std::max(gray.at<uchar>(i,j) - rand()%((int)val+1), 0);
				}
			}
		}

    		imshow("original",img);
    		imshow("image",gray);

	    	if (waitKey(1) == 'q')
	    		break;
		}
	destroyAllWindows();
}

در گام اول عکس، سیاه و سفید می‌شود. در این فرایند از دو track bar کشویی استفاده می‌کنیم. در اولین track bar حداکثر تعداد نویزی که باید به عکس اضافه شود و یا از عکس کم شود، ذخیره می‌شود. دومین track bar نشان‌دهنده درصد پیکسل‌هایی است که نویز بر روی آن‌ها اجرا می‌شود. در زمان جمع و تفریق، اگر مقدار یک پیکس بیشتر از ۲۵۵ و یا کمتر از ۰ باشد، به ترتیب بر روی ۲۵۵ یا ۰ تنظیم می‌شود.

تماشای ویدیو از طریق آدرس زیر:

https://youtu.be/GY-FVfwABr0

۳برجسته سازی

فیلتر برجسته سازی موجب می‌شود قسمتی از شی برجسته‌تر سایر بخش‌های آن شود. طبق تعریفی که ویکی‌پدیا از آن ارائه داده:

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

اعمال این فیلتر در OpenCV ساده است. در OpenCV با استفاده از کرنل‌های خاصی می‌توان این فیلتر را اجرا کرد. البته بسته به اندازه کرنل‌ها، جهت فیلتر برجسته سازی متغیر است.

فیلتر برجسته سازی
کرنل‌های متفاوتی که می‌توان از آن‌ها استفاده کرد

 

ایجاد یک کرنل کافی است. با دوران  آن به اندازه کافی کرنل به دست می‌آوریم. تغییر اندازه کرنل بر شدت برجستگی تأثیر می‌گذارد. هرچه اندازه کرنل بیشتر باشد، تأثیر برجستگی هم بزرگ‌تر خواهد بود. توجه داشته باشید که حداقل اندازه کرنل ۲×۲ است.

کد پایتون:

def kernel_generator(size):
    kernel = np.zeros((size, size), dtype=np.int8)
    for i in range(size):
        for j in range(size):
            if i < j:
                kernel[i][j] = -1
            elif i > j:
                kernel[i][j] = 1
    return kernel

def emboss(img):
    cv2.namedWindow('image')
    cv2.createTrackbar('size', 'image', 0, 8, nothing)
    switch = '0 : BL n1 : BR n2 : TR n3 : BR'
    cv2.createTrackbar(switch, 'image', 0, 3, nothing)

    while True:
        size = cv2.getTrackbarPos('size', 'image')
        size += 2 # adding 2 to kernel as it a size of 2 is the minimum required.
        s = cv2.getTrackbarPos(switch, 'image')
        height, width = img.shape[:2]
        y = np.ones((height, width), np.uint8) * 128
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        kernel = kernel_generator(size) # generating kernel for bottom left kernel
        kernel = np.rot90(kernel, s) # switching kernel according to direction
        res = cv2.add(cv2.filter2D(gray, -1, kernel), y)

        cv2.imshow('Original', img)
        cv2.imshow('image', res)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cv2.destroyAllWindows()

کد C++:

Mat kernel_generator(int size){
	Mat kernel = Mat(size,size,CV_8S,Scalar(0));
	for (int i=0; i<size; i++){
		for (int j=0; j<size; j++){
			if (i < j){
				kernel.at<schar>(i,j) = -1;
			}
			else if (i > j){
				kernel.at<schar>(i,j) = 1;
			}
		}
	}
	return kernel;
}

void emboss(Mat img){
	namedWindow("image");
	int slider = 0;
	int slider2 = 0;
	createTrackbar("size","image",&slider,8,nothing);
	createTrackbar("0 : BL n1 : BR n2 : TR n3 : BR","image",&slider2,3,nothing);

	while (true){
		int size = getTrackbarPos("size","image");
		size += 2;
		int s = getTrackbarPos("0 : BL n1 : BR n2 : TR n3 : BR","image");
		int height = img.size().height;
		int width = img.size().width;
		Mat y = Mat(height,width,CV_8U,Scalar(128));
		Mat gray;
		cvtColor(img,gray,COLOR_BGR2GRAY);
		Mat kernel = kernel_generator(size);

		for (int i=0; i<s; i++)
			rotate(kernel,kernel,ROTATE_90_COUNTERCLOCKWISE);

		Mat dst;
		filter2D(gray,dst,-1,kernel);
		Mat res;
		add(dst,y,res);

		imshow("Original",img);
		imshow("image",res);

		if (waitKey(1) == 'q')
                        break;
                }
        destroyAllWindows();
}

همان‌گونه که پیشتر نیز گفتیم، در این فرایند از دو track bar کشویی استفاده می‌کنیم. یک track bar اندازه کرنل را کنترل می‌کند. دومین track bar جهتی را که فیلتر برجسته سازی روی آن اعمال می‌شود را کنترل می‌کند. سپس یک ماسک اضافی (روی متغیر y) ایجاد می‌شود که همه مقادیر آن ۱۲۸ هستند تا یک پس‌زمینه خاکستری ایجاد کند.

مولد کرنل یک نوع کرنل پایین  ایجاد می‌کند. فرض کنید i ردیف‌ها و j ستون‌ها را نشان می‌دهد. سپس برای تمام   مقدار ۱ و برای تمامی  مقدار ۱-  را مشخص می‌کنیم و زمانی که برابر باشند از ۰ استفاده می‌کنیم. برای ایجاد یک کرنل پایین-راست (bottom-right) باید یک بار عکس را در جهت خلاف عقریه‌های ساعت بچرخانیم. برای ایجاد کرنل‌ بالا-راست (top-right) عکس را دوبار و برای ایجاد کرنل بالا-چپ (top-left) عکس را سه بار دوران می دهیم. مقادیر گزینه‌ای (switch) که نوع کرنل را کنترل می‌کند با استفاده از np.rot90 تنظیم می‌شوند، به نحوی که یک ماتریس را در جهت خلاف عقربه‌های ساعت می‌چرخاند، ماتریس مورد نیاز را در اختیار ما می‌گذارد.

با استفاده از cv2.filter2D هم کرنل با نسخه سیاه و سفید عکس ورودی می‌چرخد. آرگومان میانی عمق مورد نیاز برای ماتریس خروجی را نشان می‌دهد. در این حالت اگر یک مقدار منفی برای مثال ۱- تعیین شود، عمق ثابت باقی می‌ماند و تغییر نمی‌کند.

تماشای و.یدئو از طریق آدرس زیر:

https://youtu.be/t3j5ujVlZ84

سمت چپ: تصویر اصلی / سمت راست: نتیجه اعمال فیلتر Emboss بر روی عکس. عکس از Anastase Maragos در Unsplash

۴- Duo-Tone

همانند فیلتر ۶۰s TV این فیلتر هم از Adobe Photoshop الهام گرفته شده است. این فیلتر چه کاری انجام می‌دهد؟

Duo-Tone

همان‌گونه که در gif فوق مشاهده می‌کنید، فیلتر duo-tone یک سایه رنگی بر روی عکس اعمال می‌کند. برای به دست آوردن این جلوه، کانال رنگی گزینه‌ای برای افزایش مقدار خواهد داشت. در نتیجه افزایش مقدار هم سایه روشن‌تر خواهد شد. مقادیر سایر کانال‌ها را می‌توان کاهش داد و یا بر روی صفر تنظیم کرد تا یک سایه روشن‌ یا یک‌دست بر روی تصویر اعمال شود.

کد پایتون:

def exponential_function(channel, exp):
    table = np.array([min((i**exp), 255) for i in np.arange(0, 256)]).astype("uint8") # generating table for exponential function
    channel = cv2.LUT(channel, table)
    return channel

def duo_tone(img):
    cv2.namedWindow('image')
    cv2.createTrackbar('exponent', 'image', 0, 10, nothing)
    switch1 = '0 : BLUE n1 : GREEN n2 : RED'
    cv2.createTrackbar(switch1, 'image', 1, 2, nothing)
    switch2 = '0 : BLUE n1 : GREEN n2 : RED n3 : NONE'
    cv2.createTrackbar(switch2, 'image', 3, 3, nothing)
    switch3 = '0 : DARK n1 : LIGHT'
    cv2.createTrackbar(switch3, 'image', 0, 1, nothing)

    while True:
        exp = cv2.getTrackbarPos('exponent', 'image')
        exp = 1 + exp/100 # converting exponent to range 1-2
        s1 = cv2.getTrackbarPos(switch1, 'image')
        s2 = cv2.getTrackbarPos(switch2, 'image')
        s3 = cv2.getTrackbarPos(switch3, 'image')
        res = img.copy()
        for i in range(3):
            if i in (s1, s2): # if channel is present
                res[:, :, i] = exponential_function(res[:, :, i], exp) # increasing the values if channel selected
            else:
                if s3: # for light
                    res[:, :, i] = exponential_function(res[:, :, i], 2 - exp) # reducing value to make the channels light
                else: # for dark
                    res[:, :, i] = 0 # converting the whole channel to 0
        cv2.imshow('Original', img)
        cv2.imshow('image', res)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cv2.destroyAllWindows()

کد C++:

Mat exponential_function(Mat channel, float exp){
	Mat table(1, 256, CV_8U);

	for (int i = 0; i < 256; i++)
		table.at<uchar>(i) = min((int)pow(i,exp),255);

	LUT(channel,table,channel);
	return channel;
}

void duo_tone(Mat img){
	namedWindow("image");
	int slider1 = 0;
	int slider2 = 1;
	int slider3 = 3;
	int slider4 = 0;
	string switch1 = "0 : BLUE n1 : GREEN n2 : RED";
	string switch2 = "0 : BLUE n1 : GREEN n2 : RED n3 : NONE";
	string switch3 = "0 : DARK n1 : LIGHT";
	createTrackbar("exponent","image",&slider1,10,nothing);
	createTrackbar(switch1,"image",&slider2,2,nothing);
	createTrackbar(switch2,"image",&slider3,3,nothing);
	createTrackbar(switch3,"image",&slider4,1,nothing);

	while(true){
		int exp1 = getTrackbarPos("exponent","image");
		float exp = 1 + exp1/100.0;
		int s1 = getTrackbarPos(switch1,"image");
		int s2 = getTrackbarPos(switch2,"image");
		int s3 = getTrackbarPos(switch3,"image");
		Mat res = img.clone();
		Mat channels[3];
		split(img,channels);
		for (int i=0; i<3; i++){
			if ((i == s1)||(i==s2)){
				channels[i] = exponential_function(channels[i],exp);
			}
			else{
				if (s3){
					channels[i] = exponential_function(channels[i],2-exp);
				}
				else{
					channels[i] = Mat::zeros(channels[i].size(),CV_8UC1);
				}
			}
		}
		vector<Mat> newChannels{channels[0],channels[1],channels[2]};
		merge(newChannels,res);
		imshow("Original",img);
		imshow("image",res);
		if (waitKey(1) == 'q')
                        break;
                }
        destroyAllWindows();
}

 

از اولین track bar برای به دست آوردن یک مقدار بین ۰ تا ۱۰ استفاده می‌کنیم. سپس مقادیر نرمال‌سازی می‌شوند تا بین ۰ و ۱ باشند. سپس مقدار ۱ اضافه می‌شود که یک مقدار نمایی خواهد بود. سپس تابع نمایی با استفاده از cv2.LUT بر روی عکس اجرا می‌شود. این تابع یک کانال را دریافت می‌کند و با استفاده از یک جدول مراجعه (lookup table) ان را تبدیل می‌کند. سپس سه گزینه ایجاد می‌شوند و مقادیر آبی، سبز و قرمز به آن‌ها اختصاص داده می‌شود. البته گزینه دوم یک گزینه اضافی none هم دارد. گزینه سوم مشخص می‌کند که آیا حالت تاریک باید استفاده شود یا حالت روشن. تمامی این گزینه‌ها این امکان را برای ما فراهم می‌کنند تا از میان ۶ پالت رنگی مختلف یکی را انتخاب و بر روی عکس اعمال کنیم.

با توجه به رنگی که کاربر انتخاب کرده، مقادیر آن بر اساس تابع نمایی افزایش می‌یابند. در غیر این صورت مقدار بر روی صفر تنظیم می‌شود و کاهش می‌یابد.

تماشای ویدئو از طریق آدرس زیر:

https://youtu.be/eN2KlZVx5RE

۵Sepia (رنگ سوبیایی)

فیلتر sepia رنگ عکس اصلی را به رنگ قرمز متمایل به قهوه‌ای (سوبیایی) تغییر می‌دهد. با استفاده از این فیلتر می‌توان ظاهر نمای کلی تصویر را تغییر دارد. فیلتر Sepia فیلتر رایج و متدوالی است و تقریباً در تمامی نرم‌افزارهای ویرایش عکس یافت می‌شود.

اجرای این فیلتر در OpenCV آسان است. رنگ این فیلتر ثابت است و تغییر نمی‌کند. علاوه بر این، این فیلتر یک ماتریس استانداردسازی‌شده دارد که می‌توان به عنوان پیش‌فرض از آن استفاده کرد. البته توجه داشته باشید که OpenCV از فرمت رنگی BGR استفاده می‌کند، اما ماتریسی که به صورت آنلاین در دسترس شما قرار می‌گیرد برای فضای رنگی RGB است. بنابراین باید آن را به RGB تبدیل کنیم و پس از پردازش و پیش از نمایش دادن تصویر،  آن را مجدداً به فرمت BGR برگردانیم.

کد پایتون:

def sepia(img):
    res = img.copy()
    res = cv2.cvtColor(res, cv2.COLOR_BGR2RGB) # converting to RGB as sepia matrix is for RGB
    res = np.array(res, dtype=np.float64)
    res = cv2.transform(res, np.matrix([[0.393, 0.769, 0.189],
                                        [۰.۳۴۹, ۰.۶۸۶, ۰.۱۶۸],
                                        [۰.۲۷۲, ۰.۵۳۴, ۰.۱۳۱]]))
    res[np.where(res > 255)] = 255 # clipping values greater than 255 to 255
    res = np.array(res, dtype=np.uint8)
    res = cv2.cvtColor(res, cv2.COLOR_RGB2BGR)
    cv2.imshow("original", img)
    cv2.imshow("Sepia", res)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

 کد C++:

void sepia(Mat img){
	Mat res = img.clone();
	cvtColor(res,res,COLOR_BGR2RGB);
	transform(res,res,Matx33f(0.393,0.769,0.189,
				۰.۳۴۹,۰.۶۸۶,۰.۱۶۸,
				۰.۲۷۲,۰.۵۳۴,۰.۱۳۱));
	cvtColor(res,res,COLOR_RGB2BGR);
	imshow("original",img);
	imshow("Sepia",res);
	waitKey(0);
	destroyAllWindows();
}

پیش از اینکه از cv2.transform استفاده کنیم تا جلوه دلخواه را بر روی عکس اجرا کنیم، نوع داده تصویر به float تغییر می‌کند. هر مقداری که بیشتر از ۲۵۵ باشد به ۲۵۵ محدود می‌شود. سپس نوع داده به np.uint8 و فضای رنگی به BGR تغییر می‌کند.

نتیجه اعمال فیلتر Sepia

سمت چپ: تصویر اصلی / سمت راست: نتیجه اعمال فیلتر Sepia بر روی عکس. عکس از Quino AI در Unsplash

ممکن است این سؤال برای‌تان پیش بیاید که چرا ویدئویی برای این فیلتر تهیه نکردیم و شدت آن را به وسیله trach bar کنترل کردیم؟ برای اینکه فیلتر Sepia یک رنگ ثابت دارد و با یک آرایه ثابت می‌توان آن را به دست آورد.

چکیده

در این مقاله به شما نشان دادیم که چگونه می‌توان با استفاده از توابع OpenCV، ۵ فیلتر مختلف ایجاد کرد. Track barها این امکان را برای کاربران فراهم می‎کنند تا شدت فیلتر را بر اساس نیاز و سلیقه خود تنظیم کنند. در این مقاله فقط گوشه کوچکی از قابت‌های بی‌شمار OpenCV را به شما معرفی کردیم.

انواع کاربردهای هوش مصنوعی در صنایع مختلف را در هوشیو بخوانید

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

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

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