# Native Code > برنامه نویسی در 6 VB > برنامه نویسی مرتبط با بازی و گرافیک در VB6 >  شمارش لکه ها روی عکس

## farzad879

سلام 
یه سوال داشتم از دوستان
میخوام ببینم تو vb6 چطور میتونم تو یه عکس با زمینه تک رنگ لکه هایی که رنگ متفاوت دارن بشمارم مثلا تو این عکس عدد 8 رو بده

----------


## sa1378

فکر نکنم بشه
اگه بخوای تعداد نقطه های سیاه رو بشماری که توی خود هر لکه یه عالمه نقطه سیاه هست
اگر مثلا بگی نقطه هایی که از هم فاصله دارن و کنار هم نیستن
بازم توی هر لکه مقداری جای خالی وجود داره
خودت اگه شرطی به ذهنت رسید بگو من سعی میکنم برنامشو بنویسم

----------


## Mori Bone

شما می تونی دوتا حلقه تودرتو بزاری از 0 تا طول و 0 تا عرض عکس.بعد با Point یه پیکسل یه پیکسل ببینی مشکیه یا نه. البته فکر کنم 3.5 طول می کشه(البته اینم بگما بستگی به cpu N داره ها)

----------


## sa1378

خب این چیزی که شما گفتی فرض کنیم سی پی یو خفن باشه(بی نهایت)
ولی بازم هر لکه از تدادی point تشکیل شده

پس تعدادی که بدست میاد خیلی بیشتره
.....................................

شما دوست عزیز اگه بگین برای چه کاری اینو میخواین شاید یه راه دیگه به ذهن ما برسه

----------


## m0hamad_design

سلام
چرا انقد خودتون رو اذیت می‌کنید !

شما با متد پونیت، پیکسل به پیکسل رو بررسی کن 
هر جا که سیاه بود یعنی لکه هست . (این تا اینجا ؛ حالا:‌  )

برای اینکه تعداد نقطه های سیاهی که بدست میاری و ماله یک لکه هست به تعداد لکه های اصلی اضافه نشه ، شما میتونی چک بکنی که نقطه قبلی سیاه بوده یانه

مثلا شما تو تصویر بالا 8 تا لکه داری ، به لکه اول میرسی و اولین پیکسلش رو چک میکنی و میفهمی که لکه هست . پیکسل بعدی رو چک میکنی و بازم  میبینی که سیاه ، پس هنوز ادامه لکه هست

وقتی که پیکسل های سیاه تموم شدن ، پس اون لکه هم تموم شده و میری سراغ بعدی


شرمنده اگه خیلی خوب توضیح ندادم

----------


## m0hamad_design

یک کار دیگه هم میتونی بکنی ( برای بهترشدن )

اونم اینکه خصوصیت های ScalHeight  و  ScalWidth اون پیکچر باکس رو برابر یک عدد کوچیک تر بکنی و بعد از متد پوینت استفاده کنی

اینطوری تعداد نقاط روی پیکچرباکس ، به 100 تا ( 10 * 10 (10 تا افقی و 10 تا عمودی )) تغییر پیدا میکنه و کمتر میشه

----------


## Nabege

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

----------


## Nabege

بیا اینم برنامش تو سه صوت ساختمش آلگوریتمش هم خیلی سادست.
من اینجا پس زمینه رو سفید قرار دادم و شما می تونید اون رو عوض کنید.
البته باید بگم که این چنین برنامه هایی در رابطه با پردازش تصویر باید با زبان های با سرعت بالا مثل c و C++‎‎ نوشته بشن.

----------


## Nabege

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

----------


## Nabege

این بالایی یه ایراد جزیی داشت اصلاحش کردم.

----------


## Nabege

بفرمایید اینم نسخه بهینه شده پرسرعتش.

----------


## محمد فدوی

۱- ابتدا همه نقاط سیاه داخل صفحه رو بشمار
۲- نقاطی که فاصلشون کمتر از ۵ پیکسل (یا یکمی کمتر و بیشتر) هست رو باهم حذف کن و به جاش نقطه میانگینشون رو قرار بده و اونا رو یک لکه درنظر بگیر.
۳- مرحله قبلو اینقدر تکرار کن که همه نقاط فاصلشون از ۵ بیشتر بشه. حالا هر نقطه یه لکه ست.
۳- لکه هایی که کمتر از۱۵ نقطه (یا یکمی کمتر و بیشتر) توشون وجود داره رو خطا در نظر بگیر و حذفشون کن.
با کم و زیاد کردن عددهای بالا میتونی خطا رو به حداقل برسونی. گام بعدی که اگه خواستی پروژت رو گسترش بدی انجامش میدی اینه که به برنامت یاد بدی اون عدد های بالا رو خودش بصورت دینامیک محاسبه کنه. تکنیک های آماری ساده بت کمک میکنه (مثل آنالیز واریانس)

اگر اینکارو نکنی باید تکنیک های پیچیده Image Proccessing رو بکار بگیری که بگذریم ازشون سنگین تریم!

----------


## Nabege

فکر خیلی خوبیه ساده هم بنظر میاد با این روشی که شما گفتین سرعت خیلی بالا می آد ولی تشخیص رنگ پس زمینه یه کمی زمانبره اونو چیکار کنم؟
تکنیک های پیچیده Image Proccessing دیگه چی هستن چطور می تونم یادشون بگیرم.

----------


## محمد فدوی

> تشخیص رنگ پس زمینه یه کمی زمانبره اونو چیکار کنم؟


دو حالت وجود داره:
۱- شما می دونی تصویرت صرفا از ۲ رنگ ساخته شده و هیچ نویزی وجود نداره: در اینصورت کافیه رنگ پیکسل های صفحه رو بشماری و اونی که تعدادش کمتر بود رنگ لکه هاست و رنگ دوم رنگ پس زمینه

۲- تصویر دارای نویز هستش: در اینصورت راه های زیادی برای کاهش نویز هست... یکی از ساده ترین هاش رو بهت پیشنهاد میدم. برای این مثال ما دو تا رنگ داریم (پس زمینه و رنگ لکه ها). فرض میکنیم این دو رنگ تضاد زیادی دارن. یعنی یا پس زمینه تیرست و لکه ها روشنن یا برعکس. پس هر پیکسلی که رنگش روشن بود رو سفید کن و هر پیکسلی که رنگش روشن بود رو سیاد در نظر بگیر. برای اینکارم کافیه میانگین فاکتورهای قرمز و آبی و سبر هر پیکسل رو حساب کنی. اگر این مقدار بیشتر از۱۲۷ بود اون نقطه تیره رنگه در غیر اینصورت روشنه:
''' RED
Dim r As Integer
''' GREEN
Dim g As Integer
''' BLUE
Dim b As Integer

If (r+g+b)/3 > 127 Then
    ''' BLACK
Else
    ''' WHITE
End If

حالا ما یه تصویر داریم که فقط نقاط سفید و سیاه داره. حالا کاری که تو حالت اول انجام دادیم رو تکرار میکنیم تا رنگ پس زمینه و رنگ لکه هارو تشخیص بدیم.
بعد از تشخیص رنگ لکه ها کارایی که توی پست قبل گفتمو میتونی انجام بدی. در هر صورت کار به توان بالایی از نظر پردازش نیاز داره. تو اینجور پروژه ها یکی از مهمترین فاکتورها صرفه جویی در مصرفه! یعنی حتی از یک بایت هم نگذر! اگه میشه به جای اینکه یه متغیر رو Integer بسازی از توع Byte بسازی حتما اینکارو بکن!  :چشمک: 

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




> تکنیک های پیچیده Image Proccessing دیگه چی هستن چطور می تونم یادشون بگیرم.


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

دوتا نکته هم یادم نره بگم؛ اولا اینکه پیشنهاد میکنم تصویرت رو کوچیک کنی و باش کار کنی تا سرعت افزایش پیدا کنه. برای اینکارم لازم نیست جداگونه یه بار کوچیکش کنی و یه بار کارای بالا رو بکنی. اگه در حین اینکه کارای بالا رو میکنی مثلا ۴ تا نقطه رو باهم در نظر بگیری (یه نقطه در نظر بگیریشون) در اینصورت محاسبات شما به ۱/۴ میرسه که معادل اینه که تصویرت رو ۴ برابر کوچیک کرده باشی.
ثانیا توی کتابخوانه ی VB6 ابزار مناسبی برای پروسس های طولانی روی تصاویر وجود نداره. یا از کتابخوانه هایی که برای اینکار توی VB6 نوشته شده استفاده کن یا به سراغ فریموورک کارآمد تری مثل ++C برو.

موفق باشی.

----------


## محمد فدوی

بخش Image Proccessing  توی انجمن هست راستی!  :لبخند گشاده!:

----------


## Nabege

واسه تشخیص رنگ پس زمینه اگه به کد برنامم دقت کنی می بینی من تقریبا همین کار رو به روشی دیگر کردم ولی بلاخره در دو حالت باید دوبار تک تک پیکسل ها رو بری که بازم زمانبره ولی من یه بهینه سازی خوبی که کردم ولی خیلی تو سرعت کارآمد بود این بود که تمام نقاط تصویر رو اول تو یک آرایه با نوع long گذاشتم و بعد بررسی کردم و مستقیما از Picture.point استفاده نکردم.

----------


## محمد فدوی

خب اینکه همش نباید اطلاعات خام رو بخونی که واضحه... ولی لازم نیست دوبار عکست رو پیمایش کنی. با یه بار پیمایش هم میتونی کوچیکش کنی و هم میتونی رنگ ها رو ثبت کنی. در نهایت اونیم که تعدادش بیشتره رو به عنوان پس زمینه در نظر میگیری. در ضمن لازم نیست یه آرایه Long استفاده کنی. اینکار احتمالا Performance رو به شدت کاهش میده. چون با ۲ رنگ کار داری میتونی از یه آرایه Boolean استفاده کنی.

ویرایش:
پیشنهاد میکنم برای انتقال دیتا به آرایه دونه دونه عمل نکنی که کار بسیار بدیه! از این APIها استفاده کن.
برای پیمایش داده ها هم از Stack استفاده کن. من اینو پیدا کردم.

----------


## Nabege

حرفتون خیلی درسته، اولین باره که چنین ترفندهایی می شنوم.
ای کاش همه برنامه نویسی این طور ترفندها باشه.

----------

