پروژه اول مقایسه و تطبیق دو تا تصویر هستش که یه مثال برای computer vision هست. مثلا اینجوری که یه تصویر از یه کارت شناسایی درست و خوب داریم. بعد می خوایم یه عکس از یه کارت شناسایی دیگه رو باهاش مقایسه کنیم ببینیم تصویر دوم جعلیه یا واقعیه؟
این مقایسه چند تا مرحله داره: اول بیایم عکسا رو از کاربر بگیریم. بعد سایز و فرمت و shape اشون رو مقایسه کنیم. بعد سایز رو تغییر بدیم و دو تا تصویر رو عین هم کنیم. بعد بیایم عکسها رو سیاه و سفید کنیم. بعد بیایم similarity index یا میزان شباهت رو پیدا کنیم. بعد threshold ، بعد contour و grab رو دربیاریم. بعد دور اون contour ها یه مستطیل بکشیم و مشخصشون کنیم. بعد تفاوتها رو رسم کنیم. بعد با توجه به همه اینا یه امتیاز شباهت بدیم که دو تا عکس چقدر به هم شبیهن و اون عکس دومیه فیکه یا نه؟ حالا دونه دونه توضیح میدم.
اول چیکار میکنیم؟ میایم لایبرری هایی که نیاز داریم رو ادد میکنیم:
from skimage.metrics import structural_similarity
import imutils
import cv2
from PIL import Image
import requests
متد structural_similarity از ماژول skimage.metrics برای پردازش تصویر استفاده میشه. میاد اون similarity index رو محاسبه میکنه که در واقع شباهتهای ساختاری و مهم دو تا تصویره. imutils یه مجموعه ای از متدهاس که میاد کارای اصلی و اساسی پردازش تصویر رو برامون انجام میده مثل resize و rotate و اینا. cv2 هم که همون openCV عه . البته جمع وجورش. برای کامپیوتر ویژن. باز PIL هم یه کتابخونه پردازش تصویر توی پایتونه. request هم که برای دانلوده.
!mkdir pan_card_tampering
!mkdir pan_card_tampering/image
با این دو تا دستور هم میایم دو تا فولدر توی هم میسازیم که وقتی تصویرا رو دانلود کردیم بره توی اینجا.
original = Image.open(requests.get('https:// ... ', stream=True).raw)
tampered = Image.open(requests.get('https://...', stream=True).raw)
این دو تا دستور هم میان از یه آدرس دو تا عکس دانلود میکنن و میریزن توی دو تا متغیر. که خب از request برای دانلود و از Image برای خوندن دو تا عکس و ریختنشون توی متغیرها استفاده کردیم. اولیش اون اصلیه اس. دومیش هم اونیه که میخوایم فیک بودنش رو حساب کنیم. حالا آدرسش مهم نبود. چون طولانی میشد پاکش کردم. کد اصلی رو آخرش میذارم.
اول عکسا رو ببینیم چه شکلین. همینطوری اسمش رو بنویسم تصویر رو نمایش میده :
حالا کار شروع میشه. اول میایم سایز و فرمت دو تا تصویر رو میبینیم :
print("Original image format : ",original.format)
print("Tampered image format : ",tampered.format)
print("Original image size : ",original.size)
print("Tampered image size : ",tampered.size)
الان غیر از اینکه تصویرها هم اندازه نیستن، تصویر اصلی خیلیم بزرگه. بخاطر همین میایم ریسایز میکنیم. بعد هم توی دو تا متغیرها میریزیم. هم اینکه توی اون دو تا فولدری که ساختیم ذخیره اشون میکنیم.
original = original.resize((250, 160))
original.save('pan_card_tampering/image/original.png')
tampered = tampered.resize((250,160))
tampered.save('pan_card_tampering/image/tampered.png')
با استفاده از اون cv2 عکسا رو میخونیم، میریزیم توی همین دو تا متغیر که بعدا لازمشون داریم. این متد imread میاد عکسا رو به صورت ماتریس ذخیره می کنه.
original = cv2.imread('pan_card_tampering/image/original.png')
tampered = cv2.imread('pan_card_tampering/image/tampered.png')
مرحله بعدی اینه که برای پردازش بهتر و همینطور ساده کردن ماتریس عکسا و سبک کردنش، بیایم چیکار کنیم؟ عکسا رو سیاه و سفید کنیم. اول اینکه با اینکار لبه های قسمتهای مختلف تصویر بهتر مشخص میشه. بعد هم اینکه یه عکس رنگی 3 تا مقدار rgb داره ولی یه عکس سیاه و سفید 1 دونه مقدار داره برای هر پیکسل.
گفتیم که میخوایم یه عدد در نظر بگیریم و به میزان شباهت دو تا تصویر امتیاز بدیم. این کار با استفاده از از متد structural_similarity انجام میشه که یه عدد SSIM برمیگردونه . این میزان شباهته . که خب هر چیم عددش کمتر باشه، میزان شباهت کمتره:
(score, diff) = structural_similarity(original_gray, tampered_gray, full=True)
print("SSIM: {}".format(score))
مال این دو تا تصویر که بالا نشون دادم زیاد نیست
SSIM: 0.3167879033273942
تازه از اینجا پردازش تصویر شروع میشه. اول میایم آستانه گذاری میکنیم یا همون threshold. تقریبا میشه گفت یه روش ساده سازی تصویره. میاد تصویر رو باینری میکنه. یعنی یه پیکسل یا سفیده و 1 مدارش ، یا سیاه و 0 . البته این ساده ترین تعریفشه.
یعنی اول اومدیم تصویر رو از حالت رنگی تبدیلش کردیم به gray-scale. این سیاه و سفید نیست. خاکستری طوره. یعنی هنوزم طیف رنگ داریم. یه جاهایی پر رنگتر از جاهای دیگه اس. سایه و این حرفا رو داریم. حالا میخوایم با threshold بیایم و کاملا تصویر رو سیاه و سفید کنیم.
کار بعدی پیدا کردن contour هاس. کلا کلمه contour یعنی خط. یه contour یه خط بسته اس در تصویر که یه رنگ دارن یا مثلا یه قطر دارن. خلاصه مشخصه که در امتداد هم اند.
حالا این دو تا کار پایه ای رو از کتابخانه cv2 که همون openCV هست بر میداریم:
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
این دو تا متد این کارا رو برامون انجام میدن. یعنی اول آستانه گذاری و تبدیل عکس به عکس باینری. بعد هم چی؟ پیدا کردن خطوط که برای تشخیص اشیا در تصویر ضروریه. خروجی اش هم یه آرایه است.
حالا کار بعدی اینه که بیایم دور اشیاء موجود در تصویر یه مستطیل بکشیم. یعنی ناحیه ای که اون contour توش قرار داره رو تشخیص بدیم و یه مستطیل دورش بکشیم. این کار برای مقایسه دو تا تصویر استفاده میشه. یعنی میتونیم بزرگی و کوچیکی آبجکتهای موجود در تصویر رو با هم مقایسه کنیم. مثلا اینکه سایز شماره ID موجود در دو تا کارت یکیه؟
for c in cnts:
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(original, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.rectangle(tampered, (x, y), (x + w, y + h), (0, 0, 255), 2)
حالا کارایی که کردیم رو نمایش میدیم
print('Original Format Image')
Image.fromarray(original)
print('Tampered Image')
Image.fromarray(tampered)
print('Different Image')
Image.fromarray(diff)
print('Threshold Image')
Image.fromarray(thresh)
خب این از قسمت اول. کدهاش رو هم میذارم اینجا