پیدا کردن تفاوت های دو تصویر با opencv در پایتون
امروز میخوایم با استفاده از پایتون و opencv دو تا تصویر توی برناممون لود کنیم و تفاوت هاشون رو تشخیص بدیم.
برای این کار از متد شاخص تشابه ساختاری که سال 2004 توسط وانگ اتال معرفی شد استفاده می کنیم .
برای پیدا کردن تفاوت های دو تصویر با opencv در پایتون. برنامه ای که میخوایم بنویسیم در واقع میخواد مختصات (x,y) نقاطی که روی تصویر اختلاف وجود داره رو بدست بیاره. برای اینکه کارو شروع کنیم قبلش باید مطمئن بشیم که پایتونمون و پکیج های openCV و scikit-image و imutils روی سیستممون نصب شده باشند .
برای نصب و آماده سازی پایتون و پکیج ها میتونین از این آموزش استفاده کنین.
دو تصویر زیرو ببینید میتونین متوجه تفاوت هاش بشید:
شاید خیلی زود متوجه شدین ، شایدم نه ، ولی مهم نیست کاری که ما میخوایم بکنیم اینکه این کارو بسپریم به OpenCV, scikit-image, and Python پس بیاید بریم سر وقتش :
یه فایل جدید به اسم img-diff.py ایجاد کنید و کدهای زیرو توش بزنین تا شروع کنیم کدهامونو باهم بررسی کنیم :
# import the necessary packages
from skimage.metrics import structural_similarity as 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)
از خط 2 تا 5 پکیج هایی که لازم داریم رو به پروژه اضافه کردیم
در خط 8 و 9 دوتا عکسی که میخوایم مقایسه کنیم رو لود کردیم(باید دقت داشته باشین عکسها کنار فایل img-dif.py باشند)
در خط 12 و 13 با استفاده از cvtColor عکسهامونو سیاه و سفید کردیم
خب حالا بیاید شاخص تشابه ساختاری (Structural Similarity Index) این دو عکس رو حساب کنیم :
# compute the Structural Similarity Index (SSIM) between the two
# images, ensuring that the difference image is returned
(score, diff) = ssim(grayA, grayB, full=True)
diff = (diff * 255).astype("uint8")
print("SSIM: {}".format(score))
توی کد بالا با استفاده از compare_ssim تشابه ساختاری دو عکسو مقایسه کردیم که خروجی دو تا مقدار score و diff هستش
Score مقدار تشابه ساختاری دو عکس رو بهمون نشون میده که یک مقدار بین محدوده [-1, 1] هستش که مقدار 1 به معنی تشابه کامل (یعنی کاملا یکی هستن) و هرچی کمتر بشه و به -1 نزدیک بشه یعنی تشابه کمتره.
diff به ما یه عکس خروجی میده که درواقع همون تغییراتی هستند که ما میخوایم مختصاتشونو بفهمیم کجاست. اطلاعات ذخیره شده توی diff به صورت اعشاری توی محدوده [0, 1] هستند که ما توی خط بعدی اونو به آرایه 8 بیتی توی محدوده [0, 255] تبدیلش کردیم که بتونیم بعدا با 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)
و در نهایت کد کامل برناممون به شکل زیر است:
from skimage.metrics import structural_similarity as ssim
import argparse
import imutils
import cv2
# load the two input images
imageA = cv2.imread('1.jpg')
imageB = cv2.imread('2.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) = 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)
Comments (11)
مطلب خیلی مفیدی بود ممنون
با عرض سلام
این کد اصلا کار نمیکنه
حتی دوتا عکس یکسان هم میدم به برنامه کلی توش اختلاف پیدا میکنه در حالی که عکس های یکی هستن !!!!!!!!!!
راهنمایی بفرمایین
سلام بایستی تصاویرتو از لحاظ ابعاد و فرمت دقیقا یکی باشن تا این کد روشون عمل کنه
یک نکته دیگه هم تو کد بود که من الان دیدم و اصلاحش کردم compare_ssim منسوخ شده و از متد جدید باید استفاده کنین که تو کد بالا آپدیت شده هست
با عرض سلام
خیلی این کد به من کمک کرد و ممنون از شما
در این کد عکس ها حتما باید از لحاظ زاویه عکس برداری و نورپردازی و اندازه یکی باشن؟؟
من میخوام یک فایل سه بعدی از یک جسم که از قبل طراحی شده رو با مدل واقعی ساخته شده از اون مدل سه بعدی مقایسه کنم و بگم که چیزی که ساخته شده چقدر اشتباه با مدل سه بعدی خودش داره
از این کد استفاده کردم ولی خیلی خطا داره و با اینکه رنگ و شکل و اندازه جسم ساخته شده با مدل سه بعدی خودش یکسان هست و یک زایه یکسان رو مقایسه میکنم و تغییرات جزیی داره ولی خیلی خطا داره و درست نمیتونه تشخیص بده!!!!
از شما خواهش میکنم در این زمینه کمکم کنید ممنون میشم از شما
سلام تصاویر و کدتونو رو بفرستین بررسی کنم
با عرض سلام
لطفا یک ایمیل بدین تا باهاتون در ارتباط باشم و ارسال کنم
exir.mee@gmail.com
با عرض سلام
در کد بالا و خط
ssim(grayA, grayB, full=True)
میشه توضیح بدین که این خط کد دقیقا چه کاری انجام میده؟
من وقتی از این خط ssim و full=True را حذف کردم خروجی من تغییر کرد و گاهی اوقات بهتر شد. میشه علتش رو توضیح بدین و بگین که ssim و full=True چه کاری انجام میدهند که با حذف آن ها خروجی تغییر میکند؟؟!
با تشکر فراوان
ssim یا Structural Similarity Index دو تا تصویر رو میگیره و پیکسل هاشونو با هم مقایسه میکنه و تفاوت هاشون رو پیدا میکنه
پارامتر full=true اختیاری هستش و اگر استفاده بشه تصویر تشابه های پیدا شده هم برگردانده میشه
بیشتر ازین مطالب بزارین
در تلاشم