PDA

View Full Version : گفتگو: مشکل با GetPixel



ATmegamin
شنبه 13 تیر 1388, 23:46 عصر
سلام
دستور .GetPixel اطلاعات pixel رو به صورت Color [A=115, R=254, G=254, B=254] میده
البته برای همه ی pixel ها ! . . .
حالا سوال :
1- مشکل برنامه چیه که برای همه ی pixel ها یه کد رو بر میگردونه ؟
2- چطور میشه بجای کد رنگ ، اسم رنگ رو بده ، یا بجای سفید 0 و بجای بقیه رنگها 1 بده ؟
اینم کد برنامه :
dim str = " "
for x=0 to 50
for y=0 to 50
c= .getpixel (x,y)
","+ RichTextBox1.Text =c.tostring
next
str +=vbCrLt
next

__H2__
یک شنبه 14 تیر 1388, 18:29 عصر
سلام
برای نام هر رنگ (اگر وجود داشته باشد) میتوانید از خصیصه Name استفاده کنید


Dim name As String = bmp.GetPixel(x, y).Name;


در مورد دوم هم به راحتی میتوانید با یک If مقایسه کنید.


'VB.Net2005/2008
Dim value As Integer

If (bmp.GetPixel(x, y) = System.Drawing.Color.White) Then
value = 0
Else
value = 1
End If


'VB.Net2008
Dim value as Integer = IIf(bmp.GetPixel(x, y) = System.Drawing.Color.White, 0, 1)


البته بدیهی است که چک کردن مستقیم با White در عمل کار مناسبی نیست و شما باید یک رنج رنگی را چک کنید...
چون شاید رنگی به چشم من و شما سفید باشد ولی از نظر ریاضی و برنامه نویسی فقط 1 واحد ناقابل با سفید خالص فاصله داشته باشد!!!

ATmegamin
یک شنبه 21 تیر 1388, 13:24 عصر
علی اقا سلامکارهایی که گفته بودید رو انجام دادم ، ولی باز هم نه اسم رنگ پیکسل رو بهم داد و نه کد بقیه ی پیکسل هارو .با اینکه از for استفاده کردم ولی انگار فقط روی یک pixel داره کار میکنه!!!!چکار کنم ؟

__H2__
یک شنبه 21 تیر 1388, 15:09 عصر
سلام
تنوع رنگها بسیار بسیار زیاد است و یک بلوک 32 بیتی میتوان بیش از 4 میلیارد رنگ داشت و در بلوک 24 بیتی میتوان بیش از 16 میلیون رنگ داشت!!!
تعداد بسیار بسیار بسیار کمی از این اعداد رنگها اسمی دارند و شاید رنگی به چشم شما قرمز بیاید و انتظار داشته باشید برنامه نام "Red" را به شما پس دهد ولی ان رنگ یک و یا شاید ده ها واحد با قرمز خالص RGB فاصله داشته باشد، نتیجتاً برنامه دیگر "Red" را پس نمیدهد.

این مسئله حتی در مورد System.Drawing.Color.White هم صادق است، رنگی که به چشم شما به ظاهر سفید است دلیل نمیشود سفید مطلق RGB باشد و با System.Drawing.Color.White برابر باشد.

اگر کد پردازشی بر اساس رنگ دارید، کد شما باید یک محدوده رنگی را چک کند، مثل تفاوت مقایسه یک عدد با 123456 در مقابل مقایسه یک عدد با رنج 100000 الی 200000
امیدوارم متوجه منظورم شده باشید.

در مورد دستور GetPixel هم باید اضافه کنم اگر شی شما نمونه ای از System.Drawing.Bitmap باشد دستور فوق صحیح کار خواهد کرد.

در صورت عدم حل مشکل، پیشنهاد میکنم یک کد نمونه و پروزه خیلی کوچک و ساده و مختصر (که سریع بتوان تحلیلش کرد و ایرادش را پیدا کرد) آپلود کنید تا بهتر بتوانم بگویم مشکل کدنویسی تان کجا است و چه بخشی را باید اصلاح کنید.

ATmegamin
یک شنبه 21 تیر 1388, 20:51 عصر
hlp me plz

kernel
یک شنبه 21 تیر 1388, 21:10 عصر
از NET. سر رشته ای ندارم

ولی اگه اشتباه نکنم تابع getpixel یکی از توابع API هست که رنگ یک نقطه رو به صورت عدد long برمیگردونه

برای تبدیل عدد long مربوط به رنگ به RGB از فرمول زیر استفاده میشه :





color = GetPixel(picturebox1.hdc, i, j)
r = color Mod 256
g = (color Mod (256 ^ 2)) \ 256
b = color \ (256 ^ 2)

__H2__
یک شنبه 21 تیر 1388, 22:05 عصر
سلام

برای تبدیل عدد long مربوط به رنگ به RGB از فرمول زیر استفاده میشه
ساختار Color در دات نت که رنگ را برمیگرداند به سادگی مقادیر ARGB را میتواند جداگانه بگیرید یا تحویل دهد.



Dim color As System.Drawing.Color = curbmp.GetPixel(0, 0)
Dim r As Byte = color.R


=====


hlp me plz
متاسفانه کدهای شما مشکلات زیادی داشت ...

- اصلاً معلوم نیست به چه دلیل شما دوبار اقدام کپی و ساخت bmp جدید از نمونه اصلی کرده اید؟؟؟
باز اگر تصویر را میخواستید ویرایش کنید و در نسخه جدید قرار دهید انجام یکبار اینکار منطقی بود ولی همینطوری بدون هیچ ویرایش و کاری تحمیل هزینه دوبار کپی گرفتن از تصویر در RAM ... !!!

- در بخش بعدی شما عرض و طول کنترلر نمایشی PictureBox را گرفته اید و معیار عرض و طول تصویر قرار دادید و با ان پردازش کردید !!!!!!!!!!!!!
ابعاد PictureBox با ابعاد تصویر برابر نیست!!! تصویر در PictureBox در زمان نمایش میتواند بزرگتر و کوچک تر باشد و حساب و کتاب ندارد!!!!
و این اعداد را در متغییر x و y ریخته اید

- از همه عجیبتر آنکه شما حلقه For گذاشته اید و شمارنده ان i و j است ولی در GetPixel به جای i و j مقادیر همیشه ثابت x و y را که حاوی ابعاد PictureBox هستند استفاده کرده اید!!!
یعنی شما دارید همواره اعداد ثابتی به GetPixel میدهید، چطور انتظار دارید مقادیر مختلفی برگرداند؟؟؟

- سپس هم پردازش خود را در یک آرایه string ریخته اید و دوباره در دو حلقه جداگانه آرایه را با جمع string به یک string واحد تبدیل کرده اید ...
این کار شاید ایرادی نداشته باشد ولی بسیار بسیار بسیار کم بازده و کند است و سرعت برنامه را خیلی کاهش میدهد.

- برای کار کرد بهتر من دستور مقایسه شما را کمی تغییر دادم.
یعنی دستور اول (bmp.GetPixel(x, y) = System.Drawing.Color.Black) بوده و ایرادی هم ندارد ولی همانطور که قبلاً گفتم این دستور فقط و فقط به سیاه خالص RGB جواب میدهد و شاید به نظر شما رنگی سیاه باشد و سیاه خالص RGB نباشد...
(
یعنی جداسازی یک رنگ خاص از بین 4 میلیارد رنگ !!!!
یک چهار میلیاردم احتمال دارد این شرط برقرار شود !
)

نتیجتاً این کد را گذاشتم (bmp.GetPixel(x, y).GetBrightness() < 0.5F)
تابع GetBrightness مقادیر RGB را پردازشی مختصر میکند و عددی بین 0 و 1 میدهد که نشاندهنده میزان روشنایی رنگ مورد نظر است
(
یعنی جداسازی حدود 2 میلیار رنگ از بین 4 میلیارد رنگ
حدود 50 درصد احتمال دارد این شرط برقرار شود.
)


- در نهایت باتوجه به عدم نیاز کد فعلی من پروژه را از Framework3.5 به Framework2.0 کاهش دادم ولی همچنان باز کردن کد به VS2008 نیاز است، مخصوصاً که از ساختار IF سه بخشی جدید VB2008 هم استفاده شده.

کد اصلاح شده خودتان را دانلود کنید و برسی کنید همچنان اگر مشکلی بود بپرسید.
(طبق معمول نسخه exe ای از کد در پوشه bin قرار دادم)
موفق و پیروز باشید.

ATmegamin
یک شنبه 21 تیر 1388, 22:51 عصر
چقدر گیجم من (البته کار همیشمه)
به استادی خودتون ببخشید

ATmegamin
یک شنبه 21 تیر 1388, 23:08 عصر
راستی میخوام عکس با هر resolation ی که باز میشه مثلا 600*800 ، با یه resolation ثابت مثلا 100*100بده و بعد getpixel استفاده بشه

__H2__
یک شنبه 21 تیر 1388, 23:18 عصر
سلام


راستی میخوام عکس با هر resolation ی که باز میشه مثلا 600*800 ، با یه resolation ثابت مثلا 100*100بده و بعد getpixel استفاده بشه

برای تبدیل سایز تصویر شما دو راه دارید که یک راه ساده اش تابع GetThumbnailImage است.


Using bmp2 = bmp1.GetThumbnailImage(100, 100, null, IntPtr.Zero)

'...

End Using

ATmegamin
سه شنبه 23 تیر 1388, 08:57 صبح
ممنون ، میشه کمی (بیشتر :لبخندساده:) توضیح بدید؟
از null, IntPtr.Zero ایراد میگیره که من ازش سر نمیارم
راه دوم رو هم بگید لطفا

__H2__
سه شنبه 23 تیر 1388, 09:37 صبح
سلام
میبخشید!
null سینتکس #C است! آن قدر بین این دو زبان سوییچ میکنم که ...
کد صحیح VB.Net


'VB.Net2005/2008
Using bmp2 As System.Drawing.Image = bmp1.GetThumbnailImage(100, 100, Nothing, IntPtr.Zero)

'...

End Using



'VB.Net2008
Using bmp2 = bmp1.GetThumbnailImage(100, 100, Nothing, IntPtr.Zero)

'...

End Using

ATmegamin
سه شنبه 23 تیر 1388, 13:09 عصر
سلام
میشه یه مثال عملی بزنید؟

__H2__
سه شنبه 23 تیر 1388, 13:38 عصر
سلام
همان نمونه قبلی را اصلاح کردم ...
در این کد برای تغییر سایز از روش دوم استفاده شده ولی روش اول هم با یک تک کتیشن نوشته شده، برای سوییچ بین دو روش مختلف کافی است تک کتیشن را بین اول دو خط جابه جا کنید
( تا کدی که نیاز ندارید به توضیحات تبدیل شود و پردازش نشود)

یادآوری میکنم که استفاده از دستور Using به جای Dim باعث میشود شی در End Using نابود شود و حافظه تخصیص داده شده پاک شود.

نمونه ای از exe کامپایل شده در شاخه bin موجود است.

ATmegamin
سه شنبه 23 تیر 1388, 15:03 عصر
علی اقا واقعا ازت ممنونم
خیلی بلدی :گیج: دمت گرم :لبخند:

میشه وقتی یه gifمتحرک باز میکنیم برای هر فریم یک بار این کار انجام بشه؟
و تو TextBox پشت سر هم داده هارو بیاره؟

__H2__
چهارشنبه 24 تیر 1388, 19:57 عصر
سلام
برای جدا کردن frame های یک gif باید از خصیصه FrameDimensionsList و سپس متد SelectActiveFrame استفاده کنید.

ATmegamin
پنج شنبه 25 تیر 1388, 09:45 صبح
استاد سلام
تو MSDN هرچی بیشتردنبال این متد و خصیصه ها میگردم گیجتر میشم! :ناراحت:
میشه یه مثال بزنی؟

ATmegamin
پنج شنبه 25 تیر 1388, 20:22 عصر
آقای H_2 به دادم برس
:افسرده:

__H2__
پنج شنبه 25 تیر 1388, 21:36 عصر
سلام
مثلاً قبل از خواندن محتویات یک تصویر gif کدی مثل این بنویسید تا فریم فعال تغییر کند.

این کد فریم فعال و جاری را که الآن میتوانید اطلاعات ان را بخوانید به فریم 5 ست میکند!


Dim bmp As System.Drawing.Bitmap = ...



Dim guid() As Guid = bmp.FrameDimensionsList
If (guid IsNot Nothing) AndAlso (guid.Length > 0) Then

Dim fd As New System.Drawing.Imaging.FrameDimension(guid(0))
Dim iFrameCount As Integer = bmp.GetFrameCount(fd)

bmp.SelectActiveFrame(fd, 5)

End If

ATmegamin
جمعه 26 تیر 1388, 00:28 صبح
دوست عزیزم زحمت کشیدی
یه کتاب برای آموزش گرافیک VB.NET 2008 معرفی میکنی؟

__H2__
شنبه 27 تیر 1388, 00:28 صبح
سلام

یه کتاب برای آموزش گرافیک VB.NET 2008 معرفی میکنی؟
اگر بتوانید خودتان را عادت بدهید تا از msdn استفاده کنید (یا نسخه انلاین و یا نصبی آفلاین) خیلی خوب است و از بسیاری کتابها و pdf های انگلیسی و فارسی بینیاز خواهید شد.

مثلاً میتوانید توضیح تک تک کلاسهای گرافیکی و توابعشان و بعضاً مثال سورس کدهای ساده از ریشه زیر استخراج کنید:
http://msdn.microsoft.com/en-us/library/system.drawing.aspx

و اما در مورد کتاب، من کتابی ندیدم ولی یک pdf قدیمی به زبان انگلیسی موجود است که خوشبختانه و از شانس شما برای لینک دانلود یک جستجوی کوچکی کردم و لینک دانلودش را یافتم.
http://rapidshare.com/files/51977272/159059035X.zip

ATmegamin
دوشنبه 29 تیر 1388, 18:40 عصر
سلام
با تشکر از راهنمایی های شما
چطور میشه این قابلیت رو به برنامه داد که فایهای غیر از gif رو هم تو برنامه open کنه؟

__H2__
دوشنبه 29 تیر 1388, 20:15 عصر
سلام

چطور میشه این قابلیت رو به برنامه داد که فایهای غیر از gif رو هم تو برنامه open کنه؟
مگه الآن نمیتوانید غیر gifر ا باز کنید؟؟؟؟؟؟؟؟
دات نت اغلب پسوندهای راج مثل bmp و jpg و gif و tif و wmf و tif و... را باز میکند!

ATmegamin
چهارشنبه 31 تیر 1388, 12:01 عصر
این کدی هست که توبرنامه اضافه کردم
اشکال کار کجاست؟

ATmegamin
چهارشنبه 31 تیر 1388, 17:52 عصر
البته OpenFileDialog1.Filter رو به صورت زیر نوشتم :

Me.OpenFileDialog1.Filter = "*All Pictures|*.tif;*.png;*.wmf;*.gif;*.bmp;*.jpg"

که تو نتیجه تفاوتی نداره
مشکل بعدی اینکه فقط دوفریم اول رو باز میکنه!

__H2__
پنج شنبه 01 مرداد 1388, 22:33 عصر
سلام
کد شما کمی مشکل داشت...
کد صحیح و مطمئن اجرا برای تمام فریم ها و در هر شرایط و... این است


Dim guid() As Guid = bmp.FrameDimensionsList
Dim iFrameCount_1 As Integer
Dim fd As System.Drawing.Imaging.FrameDimension


If (guid IsNot Nothing) AndAlso (guid.Length > 0) Then
fd = New System.Drawing.Imaging.FrameDimension(guid(0))
iFrameCount_1 = bmp.GetFrameCount(fd) - 1
End If
If (iFrameCount_1 < 0) Then iFrameCount_1 = 0


For frameindex As Integer = 0 To iFrameCount_1
If (iFrameCount_1 > 0) Then 'fd IsNot Nothing
bmp.SelectActiveFrame(fd, frameindex)
End If

'Any code ...

Next