پیدا کردن تفاوت های دو تصویر با opencv در پایتون

پیدا کردن تفاوت های دو تصاویر با opencv در پایتون

پیدا کردن تفاوت های دو تصویر با opencv در پایتون

پیدا کردن تفاوت های دو تصویر با opencv در پایتون

امروز میخوایم با استفاده از پایتون و opencv دو تا تصویر توی برناممون لود کنیم و تفاوت هاشون رو تشخیص بدیم.

برای این کار از متد شاخص تشابه ساختاری که سال ۲۰۰۴ توسط وانگ اتال معرفی شد استفاده می کنیم .

برای پیدا کردن تفاوت های دو تصویر با opencv در پایتون. برنامه ای که میخوایم بنویسیم در واقع میخواد مختصات (x,y) نقاطی که روی تصویر اختلاف وجود داره رو بدست بیاره. برای اینکه کارو شروع کنیم قبلش باید مطمئن بشیم که پایتونمون و پکیج های openCV و scikit-image و imutils روی سیستممون نصب شده باشند .

برای نصب و آماده سازی پایتون و پکیج ها میتونین از این آموزش استفاده کنین.

دو تصویر زیرو ببینید میتونین متوجه تفاوت هاش بشید:

شاید خیلی  زود متوجه شدین ، شایدم نه ، ولی مهم نیست کاری که ما میخوایم بکنیم اینکه این کارو بسپریم به OpenCV, scikit-image, and Python  پس بیاید بریم سر وقتش :

یه فایل جدید به اسم img-diff.py ایجاد کنید و کدهای زیرو توش بزنین تا شروع کنیم کدهامونو باهم بررسی کنیم :

# import the necessary packages
from skimage.measure import compare_ssim
import argparse
import imutils
import cv2
 
# load the two input images
imageA = cv2.imread('0.jpg')
imageB = cv2.imread('1.jpg')
 
# convert the images to grayscale
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)

از خط ۲ تا ۵ پکیج هایی که لازم داریم رو به پروژه اضافه کردیم

در خط ۸ و ۹ دوتا عکسی که میخوایم مقایسه کنیم رو لود کردیم(باید دقت داشته باشین عکسها کنار فایل img-dif.py باشند)

 در خط ۱۲ و ۱۳ با استفاده از cvtColor عکسهامونو سیاه و سفید کردیم

خب حالا بیاید شاخص تشابه ساختاری (Structural Similarity Index) این دو عکس رو حساب کنیم :

# compute the Structural Similarity Index (SSIM) between the two
# images, ensuring that the difference image is returned
(score, diff) = compare_ssim(grayA, grayB, full=True)
diff = (diff * 255).astype("uint8")
print("SSIM: {}".format(score))

توی کد بالا با استفاده از compare_ssim تشابه ساختاری دو عکسو مقایسه کردیم که خروجی دو تا مقدار score و diff هستش

Score مقدار تشابه ساختاری دو عکس رو بهمون نشون میده که یک مقدار بین محدوده [-۱, ۱] هستش که مقدار ۱ به معنی تشابه کامل (یعنی کاملا یکی هستن) و هرچی کمتر بشه و به -۱ نزدیک بشه یعنی تشابه کمتره.

diff به ما یه عکس خروجی میده که درواقع همون تغییراتی هستند که ما میخوایم مختصاتشونو بفهمیم کجاست. اطلاعات ذخیره شده توی diff به صورت اعشاری توی محدوده  [۰, ۱] هستند که ما توی خط بعدی اونو به آرایه ۸ بیتی توی محدوده  [۰, ۲۵۵] تبدیلش کردیم که بتونیم بعدا با opencv روش پردازش انجام بدیم.

بریم سراغ ادامه کد: حالا بیاید جاهایی که به عنوان تفاوت تشخیص دادیم رو دورشون خط بکشیم :

# threshold the difference image, followed by finding contours to
# obtain the regions of the two input images that differ
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)

خب تو کد بالا با استفاده از cv2.threshold به عکس تفاوتهامون آستانه دادیم

تو خط بعدی هم با استفاده از cv2.findContours محیط های تفاوت ها رو پیدا کردیم و ریختیمشون توی cnts

 حالا کافیه که یه حلقه بنویسیم که دونه دونه مختصات های محیط هایی که پیدا کردیم رو برامون روی یه تصویر جدید بکشه و نشون بده :

# loop over the contours
for c in cnts:
	# compute the bounding box of the contour and then draw the
	# bounding box on both input images to represent where the two
	# images differ
	(x, y, w, h) = cv2.boundingRect(c)
	cv2.rectangle(imageA, (x, y), (x + w, y + h), (0, 0, 255), 2)
	cv2.rectangle(imageB, (x, y), (x + w, y + h), (0, 0, 255), 2)

توی کد بالا یه حلقه نوشتیم که به تعداد نقاطی که توی عکسمون پیدا کرده بگرده و در خط بعدیش مختصاتشون با استفاده از  cv2.boundingRect  بگیره و بریزه توی x,y,w,h  و بعد روی imagA  و imageB با استفاده از تابع cv2.rectangle یک مستطیل دورشون بکشه.

و در نهایت با استفاده از  cv2.imshow تمام عکسهامونو نشون میدیم که ببینیم چه تغییراتی انجام شده

# show the output images
cv2.imshow("Original", imageA)
cv2.imshow("Modified", imageB)
cv2.imshow("Diff", diff)
cv2.imshow("Thresh", thresh)
cv2.waitKey(0)

و در نهایت کد کامل برناممون به شکل زیر است:

# import the necessary packages
from skimage.measure import compare_ssim
import argparse
import imutils
import cv2
 
# load the two input images
imageA = cv2.imread('0.jpg')
imageB = cv2.imread('1.jpg')
 
# convert the images to grayscale
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)

# compute the Structural Similarity Index (SSIM) between the two
# images, ensuring that the difference image is returned
(score, diff) = compare_ssim(grayA, grayB, full=True)
diff = (diff * 255).astype("uint8")
print("SSIM: {}".format(score))

# threshold the difference image, followed by finding contours to
# obtain the regions of the two input images that differ
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)

# loop over the contours
for c in cnts:
	# compute the bounding box of the contour and then draw the
	# bounding box on both input images to represent where the two
	# images differ
	(x, y, w, h) = cv2.boundingRect(c)
	cv2.rectangle(imageA, (x, y), (x + w, y + h), (0, 0, 255), 2)
	cv2.rectangle(imageB, (x, y), (x + w, y + h), (0, 0, 255), 2)
 
# show the output images
cv2.imshow("Original", imageA)
cv2.imshow("Modified", imageB)
cv2.imshow("Diff", diff)
cv2.imshow("Thresh", thresh)
cv2.waitKey(0)

 

Share this post

Comment (1)

  • محمد احمدی

    مطلب خیلی مفیدی بود ممنون

    اکتبر 12, 2019 at 8:25 ق.ظ

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *