PDA

View Full Version : مقایسه پیکسل ها و میزان تفاوت



man4toman
سه شنبه 23 مرداد 1386, 12:57 عصر
سلام دوستان عزیز
من خیلی تو سی شارپ حرفه ایی نیستم و در حد متوسط واردم.
یه مشکل در مورد مقایسه پیکسل به پیکسل دوتا عکس در سی شارپ دارم.
من میخوام دو تا عکس رو با هم مقایسه کنم و بعد هر تعداد پیکسل هایی که در دو عکس با هم متفاوت هست رو خروجی بگیرم.
موندم چیکار کنم . یه مثالی تو یه پست دیگه که مقایسه پیکسل به پیکسل میکرد دیدم ولی نتونستم مشکلمو حل کنم.

کسی هست بتونه با یه مثال مشکلمو حل کنه. فرض دو تا عکس زیر رو میخوایم مقایسه و میزان پیکسل های متفاوت رو بدست بیاریم:

rasoul_ras
سه شنبه 23 مرداد 1386, 13:56 عصر
این کارو image processing می نامند
البته در مورد کاری که شما می خواهی انجام بدی می تونم به شما بگم که لطفا از فرمت bmp استفاده کنید بعد یه تحقیق کوچولو روی این فرمت بکنید خیلی ساده تر از بقیع فرمت هاست
بهد ان را در یک استریم بایت به بایت بخونید و مقایسه کنید اگه تونستم مثالی رو براتو ن اینجا قرار می دهم

rasoul_ras
سه شنبه 23 مرداد 1386, 15:27 عصر
اینم کد ولی نیاز به کار خیلی بیشتری داره :
و مخصوص bmp

man4toman
سه شنبه 23 مرداد 1386, 21:53 عصر
سورس کد رو بررسی کردم – با اینکه تا حالا تو این مطلب زیاد کار نکردم اما چیزای زیادی دستگیرم شد.
در مورد مطلب بالایی که گفتم یعنی اینکه چجوری مقدار تفاوت در پیکسل رو بصورت عددی خروجی بگیرم کسی میتونه کمک کنه .
نیاز خیلی فوری دارم.
با تشکر از دوستان.

PC2st
سه شنبه 23 مرداد 1386, 23:37 عصر
قبلا در این مورد بحث شده، عبارت "مقایسه پیکسل به پیکسل" رو جستجو کنید.

man4toman
چهارشنبه 24 مرداد 1386, 07:39 صبح
دوست عزیز من اون تاپیک رو خوندم ولی و نتونستم مشکلمو برطرف کنم . من میخوام که برنامه تعداد پیکسلی که دو عکس با هم تفاوت دارند رو بعنوان جواب نمایش داده بشه نه اینکه دو عکس شبیه هستند یا نه.

بازهم میگم من میخوام تعداد پیکسل متفاوت رو بعنوان خروجی نشون بدم. اگه کسی بتونه با یه تیکه کد نحوه خروجی گرفتن تعداد پیکسل های متفاوت رو بگه خیلی ممنون میشم.
دوستان منتظر کمکتون هستم.
با تشکر.

rasoul_ras
چهارشنبه 24 مرداد 1386, 10:19 صبح
سلام
به صورت چه جور خروجی مثلا یه عکس یا یک فایل متنی
اگه سوالت رو واضحتر بگی شاید بتونم کممت کنم
یا اگه جایگاه ان پیکسل ها رو می خوای بدنی مثلا مختصات
سعی می کنم یه مثال براتون بزارم

rasoul_ras
چهارشنبه 24 مرداد 1386, 10:54 صبح
منبع فایلهای زیر : http://www.codeproject.com
حقیقتش من خیلی وقت پیش این فایلها رو download کردم
و لینکش رو یادم نمی یومد ولی خود فایلها رو از زیر دانلود کن ؟
بدردت می خوره :

و اینم لینک یکی دیگه از آنها :
http://www.codeproject.com/cs/media/Image_Processing_Lab.asp

man4toman
چهارشنبه 24 مرداد 1386, 12:36 عصر
اول از بابت لینک و فایلها ممنون (البته اینها رو هم داشتم).

ببینید مثلا به این صورت که بگه عکس 1 و عکس 2 تعداد 20 پیکسل با هم تفاوت دارند .
فقط همینو میخوام.

rasoul_ras
چهارشنبه 24 مرداد 1386, 13:50 عصر
این کد رو از برنامه ای که فرستادم حذف کن

for (int i = 54; i < Smalllength; i++)
{
if (Second[i] == First[i])
Three[i] = 55;
else
Three[i] = Second[i];

}
و جاش این رو بذار


for (int i = 54; i < Smalllength; i++)
{
if (Second[i] != First[i])
count++;
}
MessageBox.Show(count.ToString());

man4toman
چهارشنبه 24 مرداد 1386, 16:54 عصر
خیلی ممنون از کمکتون اما وقتی جایگزین کردم این ارور رو میده :


The name 'count' does not exist in the current context

PC2st
چهارشنبه 24 مرداد 1386, 21:46 عصر
موندم چیکار کنم . یه مثالی تو یه پست دیگه که مقایسه پیکسل به پیکسل میکرد دیدم ولی نتونستم مشکلمو حل کنم.
میشه کمی بیشتر توضیح بدید که در کجای کار مشکل دارید؟

man4toman
چهارشنبه 24 مرداد 1386, 22:47 عصر
دوست عزیز من فقط اینی که اینجا گفتم رو میخوام همین:


ببینید مثلا به این صورت که بگه عکس 1 و عکس 2 تعداد 20 پیکسل با هم تفاوت دارند .
فقط همینو میخوام.

PC2st
پنج شنبه 25 مرداد 1386, 00:35 صبح
از کدهای زیر برای مقایسه استفاده کنید:



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.ShowChanges();
Application.Exit();
}
private void ShowChanges()
{
DateTime dt = DateTime.Now;
Bitmap b1 = new Bitmap("1.jpg");
Bitmap b2 = new Bitmap("2.jpg");
int iLength = b1.Size.Width;
int jLength = b1.Size.Height;
int differents = 0;
float percent;
if (b1.Size == b2.Size)
{
for (int i = 0; i < iLength; i++)
for (int j = 0; j < jLength; j++)
if (b1.GetPixel(i, j).ToArgb() != b2.GetPixel(i, j).ToArgb())
differents++;
}
percent = (float)differents / b1.Size.Width / b1.Size.Height * 100;
TimeSpan ts = DateTime.Now - dt;
MessageBox.Show(ts.TotalSeconds.ToString("00.00") + " Second\n\n" + percent.ToString("00.00") + "%");
}
}
}


اما کدهای فوق، اصلا سریع نیستند، برای مقایسه دو تصویر 400 در 300 باید حدود 10 ثانیه منتظر بمانید...
بهرحال از کدهای فوق استفاه نکنید بهتره!


اما برخلاف کدهای فوق، کدهای زیر آنچنان با سرعت عملیات مقایسه را انجام می دهند که گویا اصلا مقایسه ائی صورت نگرفته! برای مقایسه دو تصویر 400 در 300 توسط کدهای زیر، تنها 0.05 ثانیه (5 صدم ثانیه!) منتظر خواهید ماند! و به این می گن سرعت استفاده از اشاره گرها!

نمی دونم چرا خیلی ها اشاره گرها رو نادیده می گیرند و جزئی از قابلیتهای سی شارپ به حساب نمی آورند ولی ...

بهر حال، توسط کدهای زیر، دو تصویر رو مورد مقایسه قرار بدید که تنها 0.05 ثانیه زمان میگیره.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.ShowChanges();
Application.Exit();
}
private unsafe void ShowChanges()
{
DateTime dt = DateTime.Now;
Bitmap b1 = new Bitmap("1.jpg");
Bitmap b2 = new Bitmap("2.jpg");
int iLength = b1.Size.Width;
int jLength = b1.Size.Height;
int differents = 0;
float percent;
UnsafeBitmap ub1 = new UnsafeBitmap(b1);
UnsafeBitmap ub2 = new UnsafeBitmap(b2);
ub2.LockBitmap();
ub1.LockBitmap();
if (b1.Size == b2.Size)
{
for (int i = 0; i < iLength; i++)
for (int j = 0; j < jLength; j++)
if (ub1.PixelAt(i, j)->blue != ub2.PixelAt(i, j)->blue && ub1.PixelAt(i, j)->green != ub2.PixelAt(i, j)->green && ub1.PixelAt(i, j)->red != ub2.PixelAt(i, j)->red)
differents++;
}
ub1.UnlockBitmap();
ub2.UnlockBitmap();
percent = (float)differents / b1.Size.Width / b1.Size.Height * 100;
TimeSpan ts = DateTime.Now - dt;
MessageBox.Show(ts.TotalSeconds.ToString("00.00") + " Second\n\n" + percent.ToString("00.00") + "%");
}
}
public unsafe class UnsafeBitmap
{
Bitmap bitmap;
// three elements used for MakeGreyUnsafe
int width;
BitmapData bitmapData = null;
Byte* pBase = null;
public UnsafeBitmap(Bitmap bitmap)
{
this.bitmap = new Bitmap(bitmap);
}
public UnsafeBitmap(int width, int height)
{
this.bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
}
public void Dispose()
{
bitmap.Dispose();
}
public Bitmap Bitmap
{
get
{
return (bitmap);
}
}
private Point PixelSize
{
get
{
GraphicsUnit unit = GraphicsUnit.Pixel;
RectangleF bounds = bitmap.GetBounds(ref unit);
return new Point((int)bounds.Width, (int)bounds.Height);
}
}
public void LockBitmap()
{
GraphicsUnit unit = GraphicsUnit.Pixel;
RectangleF boundsF = bitmap.GetBounds(ref unit);
Rectangle bounds = new Rectangle((int)boundsF.X, (int)boundsF.Y, (int)boundsF.Width, (int)boundsF.Height);
// Figure out the number of bytes in a row
// This is rounded up to be a multiple of 4
// bytes, since a scan line in an image must always be a multiple of 4 bytes
// in length.
width = (int)boundsF.Width * sizeof(PixelData);
if (width % 4 != 0)
{
width = 4 * (width / 4 + 1);
}
bitmapData = bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
pBase = (Byte*)bitmapData.Scan0.ToPointer();
}
public void UnlockBitmap()
{
bitmap.UnlockBits(bitmapData);
bitmapData = null;
pBase = null;
}
public PixelData* PixelAt(int x, int y)
{
return (PixelData*)(pBase + y * width + x * sizeof(PixelData));
}
}
public struct PixelData
{
public byte blue;
public byte green;
public byte red;
}
}

فقط برای اینکه بتونید از کدهای فوق استفاده کنید، باید برنامه را در حالت unsafe mode کامپایل کنید.
در کدهای فوق، یک کلاس جدید پیاده سازی شده، که قبلا هم معرفیش کرده بودم، لینک منبع این کلاس هم اینه:
http://www.dreamincode.net/forums/index.php?showtopic=14788&st=0&p=144886&#entry144886

man4toman
پنج شنبه 25 مرداد 1386, 21:13 عصر
دوست من چرا نتایجش اینجوریه؟
این کد مقدار تشابه رو نشون میده یا تفاوت؟؟
چون دو عکسی که فقط 10 پیکسل فرق میکنن رو 80.55 درص نشون میده (عکسها 800*600)

PC2st
پنج شنبه 25 مرداد 1386, 21:38 عصر
تا یک چیز یادم نرفته بگم :) اون کدهائی که گذاشه بودم، در صورتی کار میکنه که قبل از ریختن کدها درون فایل Form1.cs، روی فرم دابل کلیک کنید تا رویداد Form1_Load اضافه بشه، بعدش کدها رو اضافه کنید، و گرنه کدها کار نمیکنه :)


این کد مقدار تشابه رو نشون میده یا تفاوت؟؟
همین عکسهائی که در پست اول گذاشتید رو یادتون هست؟ اونها رو باهاش چک کردم، 00.24% با هم اختلاف داشتند. شاید این عکسهای 800x600 که میگید، از نظر شفافیت و روشنائی با هم فرق داشته باشند و چون طریقه کد نویسی به گونه ای بوده که حتی کوچکترین تفاوت رو، خط مشی بکشه، پس ممکنه این حالت هم پیش بیاد.

man4toman
پنج شنبه 25 مرداد 1386, 23:38 عصر
امکانش هست که با عکسهای رنگی این حالت پیش بیاد؟؟
من از یک عکس کپی گرفتم و تغییرش دادم (عکسها رنگی بودن)

PC2st
جمعه 26 مرداد 1386, 00:10 صبح
مثال میزنم، مثلا دو فایل داریم به اسم 1.jpg و 2.jpg که این دو فایل دقیقا یکی هستند و مثلا فایل 2.jpg از روی فایل 1.jpg کپی شده بدون اینکه بخواهیم تغییری در اون ایجاد کنیم، خوب، حالا این دو فایل رو به برنامه داده و مقایسه انجام میشه و نتیجه مقایسه برابر 00.00% هست که کاملا درسته، حالا اگر فایل 2.jpg رو با برنامه ای مثل photoshop باز کنیم و بدون اینکه تغییری در آن ایجاد کرده باشیم، آنرا بخواهیم دوباره save کنیم، در واقع تغییراتی روی فایل 2.jpg صورت میگیره! بدون اینکه ما تغییری انجام داده باشیم! چون وقتی برنامه ای مثل photoshop یک فایل jpg رو ذخیره میکنه، همانطور که میدونید فرمت jpg در خودش فشرده سازی هم داره و برای فشرده سازی روی کیفیت تصویر هم تاثیر میگذاره، پس وقتی که فایل 2.jpg رو توسط photoshop ذخیره کنیم، این برنامه ها، میان و تغییری روی نحوه فشرده شدن فایل 2.jpg میگذارند، پس همین تغییر روی نحوه فشرده سازی، باعث تغییر در کیفیت پیکسلها میشه (در حد خیلی ناچیز ولی برنامه ای که اینجا نوشته شده، به کوچکترین تغییری حساسه) پس بعد از ذخیره شدن عکس توسط photoshop، کیفیت عکس 2.jpg میتونه تغییر پیدا کرده باشه، و همین باعث ایجاد تفاوت بین دو عکس میشه.

برای اینکه چنین تفاوتهائی بخاطر نحوه ذخیره کردن پیش نیاد، فایلی رو با برنامه مثلا MS Paint باز کنید، و یک عکس رو توی MS Paint، کپی کنید، عکس رو ذخیره کنید، بعدش یک یا چند خط روی عکس بکشید و بدون تغییر فرمت عکس، آنرا تحت عنوان نام دیگری، ذخیره کنید، در آخر سر این دو فایل رو با هم مقایسه کنید.

man4toman
جمعه 26 مرداد 1386, 13:33 عصر
کاملا درسته
میخواستم همین مطلب رو الان پست کنم.
اشکال کار من هم همین بود.
یک عکس رو با Paint دستکاری و سیو کردم که این مشکل پیش اومد.