PDA

View Full Version : سوال: مقایسه دو تصویر و به دست آوردن نقاط اختلاف آنها



new delhpi coder
جمعه 20 بهمن 1391, 21:02 عصر
سلام به همه
آقای عباسی برنامه کوچکی در رابطه با مشاهده دسکتاپ کلاینت ها در شبکه نوشتن که از لینک زیر قابل دریافته
مشاهده دسکتاپ کلاینت ها در شبکه (http://barnamenevis.org/showthread.php?209792-%D8%B3%D9%88%D8%B1%D8%B3%D9%87%D8%A7%D9%8A-%D9%86%D9%85%D9%88%D9%86%D9%87-%D8%A2%D9%85%D9%88%D8%B2%D8%B4%D9%8A&p=1695693&viewfull=1#post1695693)
این نمونه یک مشکل داره اونم حجم زیاد اطلاعاتی که باید جابه جا بشه
من می خوام توی کلاینت در بازه های زمانی مختلف از صفحه عکس بگیرم و اون عکس رو با یک عکس قبل تر مقایسه کنم و فقط قسمت های رو که تغییر کرده به سرور بفرستم و در سرور تصویر رو با توجه به تصویر قبلی باز سازی کنم
برای این کار چه پیشنهادی دارید؟
اگه ممکنه یک نمونه قرار بدید؟
یا گر راه سریعتری هست لطفاً بگین.

BORHAN TEC
جمعه 20 بهمن 1391, 22:27 عصر
سلام
قبلاً هم دقیقاً بحثی در رابطه با این موضوع صورت گرفته بود:
http://barnamenevis.org/showthread.php?378177

new delhpi coder
شنبه 21 بهمن 1391, 08:37 صبح
سلام
قبلاً هم دقیقاً بحثی در رابطه با این موضوع صورت گرفته بود:
http://barnamenevis.org/showthread.php?378177

سلام
ممنون از راهنماییت
با خوندن اون تاپبک مخصوصاً نوشته های آقا مصطفی ،از نظر تئوری فهمیدم باید چکار کنم اما هر کاری کردم نتونستم پیاده سازیش کنم.

اگه میشه یه نمونه کد بذارید.

بهروز عباسی
دوشنبه 23 بهمن 1391, 17:51 عصر
درود
اینم یک کد توب برای مقایسه و به دست آوردن اختلاف دو تصویر ،
اونم با سرعت بالا:کف:
و البته ساخت خودی:لبخند:
(سرهم کردن تصویر توی سرور با خودت)


99915

procedure TForm1.btn_RunClick(Sender: TObject);
function Get_PixelSize(Ainformat: TPixelFormat): Integer;
begin
case Ainformat of
pf8bit:
Result := 1;
pf16bit:
Result := 2;
pf24bit:
Result := 3;
pf32bit:
Result := 4;
else
Result := 0;
end;
end;
function Difference(Bitmap1, Bitmap2: TBitmap): TBitmap;
type
TRGBTripleArray = packed array [WORD] of TRGBTriple;
pRGBTripleArray = ^TRGBTripleArray;
var
SPTR_1, SPTR_2: Pointer;
X, Y: Integer;
R, R1, G, G1, B, B1, PixelSize: byte;
Temp: TBitmap;
ColorRow, ColorRow1: pRGBTripleArray;
Ret: Boolean;
begin
if (Bitmap1.Width = Bitmap2.Width) and (Bitmap1.Height = Bitmap2.Height) and
(Bitmap1.PixelFormat = Bitmap2.PixelFormat) then
begin
Temp := TBitmap.Create;
Temp.PixelFormat := Bitmap1.PixelFormat;
Temp.Height := Bitmap1.Height;
Temp.Width := Bitmap1.Width;
PixelSize := Get_PixelSize(Bitmap1.PixelFormat);
for Y := 0 to (Bitmap1.Height - 1) do
begin
ColorRow := Bitmap1.ScanLine[Y];
ColorRow1 := Bitmap2.ScanLine[Y];
SPTR_1 := Bitmap1.ScanLine[Y];
SPTR_2 := Bitmap2.ScanLine[Y];
Ret := CompareMem(SPTR_1, SPTR_2, Bitmap1.Width * PixelSize);
if Ret = false then
begin
For X := 0 To Bitmap1.Width - 1 do
begin
R := ColorRow[X].rgbtRed;
G := ColorRow[X].rgbtGreen;
B := ColorRow[X].rgbtBlue;

R1 := ColorRow1[X].rgbtRed;
G1 := ColorRow1[X].rgbtGreen;
B1 := ColorRow1[X].rgbtBlue;

if RGB(R, G, B) <> RGB(R1, G1, B1) then
Temp.Canvas.Pixels[X, Y] := RGB(R, G, B)

end;
end;
end;
if Temp = nil then
ShowMessage('');
Result := Temp;
end;
end;

(* ----------------------------------------------------------- *)

var
Freq, StartCount, StopCount: int64;
TimingSeconds: real;
begin
QueryPerformanceFrequency(Freq);
QueryPerformanceCounter(StartCount);
(* ----------------------------------------------------------- *)
img_3.Picture.Graphic := Difference(img_1.Picture.Bitmap,
img_2.Picture.Bitmap);
(* ----------------------------------------------------------- *)
QueryPerformanceCounter(StopCount);
TimingSeconds := (StopCount - StartCount) / Freq;

ShowMessage(FloatToStr(TimingSeconds));
end;


نکته : توی این خط از برنامه باید پارامتر اول عکسی باشه که تغییر کرده و دومی عکسی که قبلاً گرفتی.
(* ----------------------------------------------------------- *)
img_3.Picture.Graphic := Difference(img_1.Picture.Bitmap,
img_2.Picture.Bitmap);
(* ----------------------------------------------------------- *)

همگی موفق باشید.
اگر کسی راه بهتری داشت لطفاً در صورت امکان مطرح کنه تا ما هم استفاده کنیم

یوسف زالی
دوشنبه 23 بهمن 1391, 22:38 عصر
این هم روش من،
چند وقت قبل با حمزه نوشتمش:


uses JPEG, Types;

function GetBitMap24bitDifference(BMP1, BMP2: TBitmap; ResultBMP: TBitmap): TRect;
type
TRGBTripleArray = array [word] of TRGBTriple;
pRGBTripleArray = ^TRGBTripleArray;
var
i, j: integer;
line1, line2, line3: pRGBTripleArray;
begin
ResultBMP.Width := BMP1.Width;
ResultBMP.Height := BMP1.Height;

with Result do
begin
Left := ResultBMP.Width;
Right := -1;
Top := ResultBMP.Height;
Bottom := -1;
end;

for j := 0 to BMP1.Height -1 do
begin
line1 := BMP1.ScanLine[j];
line2 := BMP2.ScanLine[j];
line3 := ResultBMP.ScanLine[j];

if CompareMem(line1, line2, BMP1.Width * 3) then
Continue;

for i := 0 to BMP1.Width -1 do
begin
if (line1[i].rgbtBlue <> line2[i].rgbtBlue)
or (line1[i].rgbtGreen <> line2[i].rgbtGreen)
or (line1[i].rgbtRed <> line2[i].rgbtRed) then
begin
line3[i].rgbtBlue := line2[i].rgbtBlue;
line3[i].rgbtGreen := line2[i].rgbtGreen;
line3[i].rgbtRed := line2[i].rgbtRed;

with Result do
begin
if Left > i then
Left := i;

if Right < i then
Right := i;

if Top > j then
Top := j;

if Bottom < j then
Bottom := j;
end;
end
else
begin
line3[i].rgbtBlue := 255;
line3[i].rgbtGreen := 255;
line3[i].rgbtRed := 255;
end;
end;
end;

with Result do
begin
if Left = ResultBMP.Width then
Left := 0;
if Right = -1 then
Right := 0;
if Top = ResultBMP.Height then
Top := 0;
if Bottom = -1 then
Bottom := 0;
end;
end;

.
.
{test only}
procedure TForm1.Button1Click(Sender: TObject);
var
bmp1, bmp2, bmp3, bmp4: TBitmap;
JPG: TJPEGImage;
R: TRect;
begin
bmp1 := TBitmap.Create;
bmp2 := TBitmap.Create;
bmp3 := TBitmap.Create;
bmp4 := TBitmap.Create;

bmp1.LoadFromFile('1.bmp');
bmp2.LoadFromFile('2.bmp');
bmp3.PixelFormat := pf24bit;
bmp4.PixelFormat := pf8bit;

R := GetBitMap24bitDifference(bmp1, bmp2, bmp3);

bmp4.Width := R.Right -R.Left +1;
bmp4.Height := R.Bottom -R.Top +1;

bmp4.Canvas.CopyRect(bmp4.Canvas.ClipRect, bmp3.Canvas, R);

JPG := TJPEGImage.Create;
JPG.Assign(bmp4);
JPG.CompressionQuality := 50;
JPG.Compress;

JPG.SaveToFile('3.jpg');

bmp1.Destroy;
bmp2.Destroy;
bmp3.Destroy;
bmp4.Destroy;
JPG.Destroy;
end;



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

BORHAN TEC
دوشنبه 23 بهمن 1391, 23:00 عصر
سلام

برای فرستادن روی شبکه خیلی خوب جواب می ده.
اندازه ی عکس به اندازه ی فریم اختلاف اونهاست.
ایده خیلی خوبیه ولی در این مدلی که شما پیاده کرده اید فرمت تصویری که ارسال میشه هم خیلی مهمه، چون فریم اختلاف دو تصویر هم به نوبه خودش میتونه بزرگ باشه. برای حل این مشکل میشه همون فریم اختلاف را هم تکه تکه کرد. مثلاً توی یک تکه کوچک فقط علامت تیک و در یک فریم کوچک دیگر فقط همون علامت ضربدر و در فریم دیگر هم فقط همون کلمه تست باشه. در روش دیگری که به ذهن بنده حقیر میرسه، از اونجایی که فریم اختلاف دو تصویر زمینه یک رنگ و ساده داره میشه دنبال یک فرمت تصویر گشت که اطلاعات مربوط به این زمینه رو نگه نداره و یا به صورت خیلی کم حجم تر اون رو نگهداری کنه. به عنوان مثال اگر از فرمت Bitmap استفاده کنید برای هر پیکسل تعداد مشخصی بایت حافظه اختصاص داده می شود که برای این کار فرمت خوبی نیست. از طرفی هم دقیقاً نمیدانم کدام فرمت برای این کار از همه بهتر است و باید کمی تحقیق در این رابطه صورت بگیره.
موفق باشید...

یوسف زالی
سه شنبه 24 بهمن 1391, 00:11 صبح
درست می فرمایید.
Gold می گفت فرمت Gif مناسبه از این بابت که نقاطی رو می شه "خالی" در نظر گرفت. اما باهاش کار نکردم.
ایده ی شما ایده ی خوبیه. اما شاید برنامه نویسی عجولانه فقط زمان رسیدن بهش رو کندتر کنه. خیلی دقت می خواد که بفهمی تصویر از کجا یکپارچگی خودش رو از دست میده.
یک ایده که الان به ذهنم می رسه اینه که وسط همون کد بعد از یک دوره "آرامش" در اختلاف اونها رو وارد تصویر دیگه ای کنیم. دقیقا مثل کاری که در فهمیدن فریم کردیم.
اما این روش می تونه نتیجه ی عکس هم بده. اگر تعداد تصاویر به دست آمده از اختلاف از حد خاصی بگذره سربار حاصل از پروسس و همچنین سربار خود تصاویر می تونه برنامه رو کند تر و مجموع حجم فایل های خروجی رو بزرگتر کنه.

firststep
سه شنبه 24 بهمن 1391, 00:28 صبح
سلام دوستان
vnc و پروتکل fbr هم همین کار رو یعنی کنترل دسکتاپ رو از توی نت در اختیارمون قرار میده اما کسی زیاد در موردش سخنی نگفته....
برنامه های زیادی هستن که فقط کافی به موتوره اونها وصل شین و تصاویر رو د ریافت واطلاعات را ارسال نمایید به موتور در سرور ::::: کسی بوده که تاحالا با اینجور برنامه ها در دلفی کار کنه؟؟؟؟؟؟

Mask
سه شنبه 24 بهمن 1391, 15:55 عصر
vnc و پروتکل fbr
این نوع پروتکل ها چون مستندات قوی در دلفی ندارند ، زیاد به کار گرفته نمیشوند در این زبان.
فارغ از اینکه خودمون با سوکت این کار رو انجام بدیم و یا بر اساس قوانین اون پروتکل بسته های پکت رو تولید و در شبکه روانه کنیم.

ایده ی شما ایده ی خوبیه. اما شاید برنامه نویسی عجولانه فقط زمان رسیدن بهش رو کندتر کنه. خیلی دقت می خواد که بفهمی تصویر از کجا یکپارچگی خودش رو از دست میده.
یک ایده که الان به ذهنم می رسه اینه که وسط همون کد بعد از یک دوره "آرامش" در اختلاف اونها رو وارد تصویر دیگه ای کنیم. دقیقا مثل کاری که در فهمیدن فریم کردیم.
اما این روش می تونه نتیجه ی عکس هم بده. اگر تعداد تصاویر به دست آمده از اختلاف از حد خاصی بگذره سربار حاصل از پروسس و همچنین سربار خود تصاویر می تونه برنامه رو کند تر و مجموع حجم فایل های خروجی رو بزرگتر کنه.
دقیقا درسته. سربار همچین محاسباتی بیشتر از سربار ارسال در شبکه میشه.
به نظر من یه راهه دیگش هم اینه که قسمتهای سفید عکس رو برابر با هیچی قرار بدیم.
و یه روش دیگه اینکه تصویر حاصله رو در 3 تصویر تک رنگ ارسال و سمت سرور با هم یکی بشوند.
البته تست نکردم . اما به لحاظ کم شدن سایز و ارسال راحتتر در شبکه ممکنه حرفی برای گفتن پیدا کنه. البته باید تست کنم.

یوسف زالی
سه شنبه 24 بهمن 1391, 17:03 عصر
فرمت فایل های تصویری اختلاف فاحشی در مونوکروم و رنگی دارند.
واقعا آفرین.
البته باید به این هم فکر کنی که باید برای این که اختلاف فاحشی بدست بیاری مونوکروم یک بیتی استفاده کنی که در نهایت فایل خروجی رو به 8 رنگ تنزل می ده. وگرنه اگر قراره طیف سیاه و سفید داشته باشی مجموع تصاویر خروجی به اندازه ی دو تا هدر نسبت به تصویر رنگی افزایش خواهد داشت.
در حالت مونوکروم تک رنگ و بدون طیف ممکنه همچنان با خنگ بازی فرمت هایی مثل JPG در حجم های کوچیک روبرو بشی.