خوراک پی سی کدنویس

ورود کاربران

آمار سایت

اعضا : 550
محتوا : 76
پیوندها : 6
بازدیدهای محتوا : 334081

حاضرین در سایت

 62 مهمان حاضر

برای نمایش بهتر سایت، از مرورگر استاندارد فایرفاکس استفاده کنید! مرورگر اینترنت اکسپلورر متعلق به دهه گذشته است!

firefox icon

Valid XHTML 1.0 Transitional Valid CSS!

خداحافظ

توجه: باز شدن در یک پنجره جدید. PDFچاپنامه الکترونیک

نوشته شده توسط مدیر سایت جمعه 18 اسفند 1391 ساعت 10:18


متاسفانه به دلیل کمبود وقت و عدم امکان به روز رسانی، این سایت به زودی تعطیل خواهد شد، اگر تمایل به خرید دامنه سایت (p30codenevis.ir) را دارید، با آدرس farsiocr at gmail تماس حاصل فرمایید.

اگر بتوانم، جهت بایگانی، مطالب سایت را به زیر دامنه edu.andishehonline.ir منتقل خواهم کرد.

سایت پرشیانگار هم که روی همین دامنه و هاست، کار می کرد به آدرس جدید http://farsiocr.ir منتقل شد.

خسروی

 

کتابخانه تشخیص پلاک خودرو به زبان ++C

توجه: باز شدن در یک پنجره جدید. PDFچاپنامه الکترونیک

نوشته شده توسط مدیر سایت جمعه 17 شهریور 1391 ساعت 17:30

با سلام خدمت خوانندگان محترم سایت آموزش برنامه نویسی ++C

متاسفانه به دلایلی چند سایت مرتب به روز نمی شود، یکی از دلایل، مشکلاتی است که سیستم مدیریت محتوای سایت (جوملا 1.5) دچار شده و دنبال فرصتی هستم تا کلا به وردپرس یا نسخه های جدیدتر جوملا جابجا شوم. انشاءالله! دلیل عمده دیگر مشغله کاری است که البته می‌شود جبران کرد اگر تنبلی بگذارد!

اما بهانه‌ی به روز رسانی امروزم، یک سوء استفاده‌ی تجاری است! که مدتهاست قصد دارم آن را منتشر کنم.

سامانه شناسایی پلاک خودرو (Automatic Number Plate Recognition)

تشخیص خودکار پلاک خودرو، از مهمترین نیازهای سیستم‌‌های کنترل خودکار ترافیک است. روزانه صدها و شاید هزاران تخلف ترافیکی روی می‌دهد و توسط دوربینهای مخصوص، تصویر خودروی متخلف ضبط می‎شود. اگر قرار باشد تمام این تصاویر توسط انسان بررسی شده و شماره پلاک خودرو به صورت دستی وارد شود، زمان و نیروی انسانی زیادی تلف خواهد شد. لذا تشخیص خودکار موقعیت پلاک خودرو و شناسایی شماره پلاک توسط نرم افزار اهمیت می‌یابد.

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

چند سال قبل، برنامه‌ای برای تشخیص پلاک خودرو نوشته بودم که برای یکی دو پروژه به کارم آمد و پس از آن مدتها خاک می‌خورد. در ماه مبارک امسال دوباره سراغ آن رفتم و به قصد تجاری سازی بهتر، تکمیلش کردم. این پروژه که به زبان ++C نوشته شده است، با استفاده از تکنیکهای پردازش تصویر و شناسایی الگو به سرانجام رسید در قالب یک کتابخانه قابل استفاده در زبانهای C++ ، C و #C آماده شد. از برخی قابلیتهای ساده OpenCV هم کمک گرفته ام لیکن بخش عمده برنامه مستقل از OpenCV است.

سامانه تشخیص پلاک خودرو

برای اطلاع بیشتر و دانلود برنامه، مقاله را دنبال کنید.

ادامه مطلب: کتابخانه تشخیص پلاک خودرو به زبان ++C

 

تفاوت برنامه نویسی MFC و WIN32 در ویژوال سی

توجه: باز شدن در یک پنجره جدید. PDFچاپنامه الکترونیک

نوشته شده توسط مدیر سایت دوشنبه 23 خرداد 1390 ساعت 12:30

در محیط ++Visual C پروژه های متنوعی می توانید ایجاد کرد که دو نوع آنها استفاده بیشتری دارد. یکی پروژه های MFC و دیگری Win32.
این دو نوع پروژه چه تفاوتی دارند و به چه کارمان می‌آیند؟
تفاوت آنها با پروژه‌ی کنسول ساده چیست؟
با ما همراه باشید...

پروژه های Win32

از اسم win32 پیداست که منظور پروژه هاییست که برای ویندوز 32 بیتی نوشته می شود (البته اگر شما برنامه 64 بیتی هم بخواهید بنویسید باز همین نوع پروژه را می توانید استفاده کنید). ویندوز یک سری کتابخانه های پویا یا همان dll دارد که در این کتابخانه ها توابع متعددی برای کار با پنجره ها در محیط ویندوز وجود دارد. این توابع که به عنوان API (مخفف Application Programming Interface) مشهور هستند نوشته شده اند که کار میکروسافت و سیستم عامل ویندوزش راه بیفتد. لیکن مایکروسافت زحمت کشیده و بخش عظیمی از این API را در اختیار برنامه نویسان هم قرار داده که کار آنها هم لنگ نماند. مثلا تابع MessageBox که یک پیام را نمایش می دهد، یا تابع CreateWindowEx که یک پنجره ایجاد می کند، یا تابع ShellExecute که یک برنامه را اجرا می کند و یا تابع GetCommState که وضعیت پورت Com (ارتباط سریال) را مشخص می کند و توابعی از این دست، همگی در فایلهایی مثل user32.dll و kernel32.dll و ... تعریف شده اند.
به کمک این توابع شما می توانید پنجره بسازید، دکمه تعریف کنید، منو بسازید، نوار ابزار ایجاد کنید و هر آنچه در یک برنامه تحت ویندوز نوعی می بینید، ایجاد کنید. لیکن تمام کارها در قالب کدنویسی صورت می گیرد.

با تعریف پروژه win32 به طور پیش فرض فایل سرآیه‌ی windows.h به پروژه شما اضافه شده، فایلهای lib لازم (مثل user32.lib و kernel32.lib) هم در تنظیمات پروژه اضافه شده و تقریبا تمام توابع لازم برای کار با پنجره ها در اختیار شما قرار می گیرد. اگر این کارها را به صورت دستی در یک پروژه کنسول ساده انجام دهید نیازی به تعریف پروژه win32 ندارید!

پروژه های Microsoft Foundation ClassesMFC

MFC مخفف Microsoft Foundation Classes یعنی کلاسهای پایه ای میکروسافت، کتابخانه ای است که شرکت میکروسافت جهت تسهیل برنامه نویسی برای ویندوز توسعه داده است. این کتابخانه چیزی نیست جز تعدادی کلاس که به صورت پوششی بر روی API ویندوز قرار گرفته و کار کردن با پنجره ها را باز هم آسانتر کرده است. به عبارتی هزاران توابع موجود در API در قالب تعدادی کلاس و به صورت مرتب درآمده اند. مثلا توابع کار با پنجره در کلاس CWnd قرار گرفته اند؛ توابع کار با دکمه در کلاس CButton و توابع کار با دیالوگ در کلاس CDialog واقع شده اند. بسیاری از کلاسهای MFC از جمله CButton، CDialog، CEdit و CRichEdit فرزند کلاس CWnd هستند.
به کمک این نوع پروژه شما می توانید، منو، دیالوگ، نوار ابزار و حتی ریبون (ویژوال استودیو 2010) را به صورت دیداری طراحی کنید و فقط کدهای لازم برای مدیریت رویدادها (مثل کلیک روی یک منوی خاص) را می نویسید. در این نوع پروژه کلاسهایی مثل CImage برای کار با تصاویر، CButton برای کار با دکمه، CFont برای کار با قلمهای ویندوز، CMenu برای منوها و ده ها کلاس متنوع دیگر وجود دارد که برنامه نویسی تحت ویندوز را بسیار تسهیل می کند.

با همه این تفاسیر کار کردن با پروژه های MFC نسبت به زبانهایی مثل #C و ویژوال بیسیک بسیار سخت تر است! به عنوان مثال در #C به محض ساختن یک Text Box با نام edit1 متغیری با همین نام در اختیار شما قرار می گیرد که به راحتی می توانید با آن کار کنید (متن آن را بخوانید یا تغییر دهید یا رنگ آن را عوض کنید) لیکن در MFC باید یک متغیر به آن تخصیص دهید و یا با دستوری مثل GetDlgItem پنجره مربوط به آن Text Box را گرفته و سپس با آن کار کنید. آن هم نه همه کاری! مثلا کارهای ساده ای مثل تغییر رنگ یک کنترل در MFC به سختی پشتک بارو زدن است! کاری که در سایر زبانها در زمان طراحی قابل انجام است. البته همین امر هم سبب شده که برنامه های نوشته شده با ویژوال سی نسبت به سایر زبانها بسیار سریعتر باشند (هر زبان را بهر کاری ساختند!)
   

جبران گذشته و رهایی از سردرگمی

آخرین به روز رسانی در شنبه 24 ارديبهشت 1390 ساعت 11:50 نوشته شده توسط مدیر سایت شنبه 17 ارديبهشت 1390 ساعت 09:07

نظر یکی از کاربران

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

 

این سوال یکی از مراجعین سایت است که البته سوال بسیاری از دیگر مراجعین هم بوده و احتمالا هست. با توجه به اینکه هر روز با دانشجویان سر و کار دارم می دانم که این یکی از بزرگترین مشکلات دانشجویان است. در این نوشته قصد ریشه یابی و ارائه راه حلی در خور وسع خودم دارم.

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

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

مشکل از آنجا آغاز می شود که در نظام آموزشی ما دانش آموزان و حتی دانشجویان وادار به تفکر نمی شوند. غالب تکالیف، تقلیدی است. شما باید کتابی را بخوانید و همان را پس بدهید. هیچگاه تشویق نمی شوید که درباره زندگیتان، آینده شغلی تان، کاربرد رشته خودتان در جامعه تفکر کنید. کم می شود که مثلا استادی یا معلمی بگوید این درسی را که می خوانید چه کاربردی دارد و در آینده به چه دردتان خواهد خورد. دانشجویان هم سراغ چنین سوالاتی کمتر می روند و چون دَورهم هستند و خوشند نگران نیستند. حدیث است که می فرماید وقتی بلایی همه گیر شد، تحملش آسان می شود. این موضوع شده است بلای همه گیر، دانشجویان به یکدیگر نگاه می کنند می بینند دوستانشان دارند گیم بازی می کنند یا قهوه تلخ می بینند، آنها هم تشویق می شوند که بی خیال باشند. (البته همیشه استثنائاتی وجود دارند)

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


  • یکی اینکه با همین تحصیلات آبدوغ خیاری برویم و در جایی استخدام شویم؛ این جا اگر دولتی بود که زیاد به جایی بر نمی خورد و باز دور هم هستیم! لیکن اگر خصوصی بود ناچاریم تازه شروع کنیم به یادگیری

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

  • سوم اینکه ادامه تحصیل دهیم، شاید که جبران مافات کنیم. این کار البته دردسرش بیشتر است، چون در فوق لیسانس دیگر خودمان هم وظیفه ای داریم. باید برای هر درسی یکی دو سمینار ارائه دهیم، باید با کتابهای لاتین کنار بیاییم و حتی پیش فرضهای استاد را هم بپذیریم. مثلا استاد انتظار دارد که اولین پروژه درسی را با نرم افزار متلب (MATLAB) بنویسیم ولی ما تا کنون نمی دانستیم که به جز زبان پاسکال و C زبان دیگری هم برای برنامه نویسی هست!

بحث من در مورد افرادیست که گزینه سوم را انتخاب می کنند:

ماهی را هر وقت از آب بگیرید تازه است

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

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

تجربه شخصی در دوران کارشناسی ارشد

من در یک شرکت مخابراتی مشغول کار بودم، تقریبا با رشته درسی ام (الکترونیک) و علاقه شخصی ام (برنامه نویسی) سازگار بود. لیکن زمانی که به دنبال تعیین استاد راهنما بودم با یکی از اساتید دانشکده صحبت کردم. متوجه شدم علاقه زیادی به مبحث OCR و شناسایی الگو دارم. این شد که درسهای مرتبط را برداشتم (شبکه عصبی، شناسایی الگو و پردازش تصویر) آنگاه به دنبال شرکتی رفتم که در این زمینه کار می کرد. به زودی شغلم را عوض کردم! و پایان نامه ام را در همان زمینه ای تعیین کردم که در شرکت جدید مشغول کار شده بودم! با این کار در تمام مدت فوق لیسانس من تقریبا کارمند دائم آن شرکت هم بودم... همین اتفاق در دوران دکتری هم تکرار شد. به لطف خدا و توفیق حضور در شرکت مذکور، در چندین پروژه ملی در زمینه شناسایی الگو همکاری داشتم.

موانع سر راه

و آمّا! بدانید که اگر با پایه ضعیف وارد دوره کارشناسی ارشد شوید (مخصوصا در رشته های فنی) با موانع زیادی رو به رو خواهید شد. مثلا شما زبان انگلیسی تان خوب نیست، لیکن کتابها و مقالاتی که استادتان معرفی می کند انگلیسی است. شما با نرم افزارهای شبیه سازی و زبانهای برنامه نویسی آشنایی ندارید لیکن هر دو هفته باید یک پروژه تحویل دهید. شما در ریاضیات 1 و 2 ضعف دارید لیکن باید فرمول های عجیب و غریب پای تخته را با تکان سر بپذیرید. (یعنی ناچارید بپذیرید که لااقل پیش سایر دانشجویان کم نیاورید) اینها واقعا مشکل است؛ بنده دارم از نزدیک می بینم. لیکن باید جبران کرد. اگر الان جبران نکنید لابد در خدمت مقدس سربازی جبران خواهید کرد؟!

کوچک که بودم برایم پذیرفتن این حدیث خیلی سخت بود: ساعتی تفکر بهتر است از هفتاد سال عبادت. الان سالهاست که دیگر برایم سخت نیست!

موفق باشید

 

 

خوشه یابی با الگوریتم K میانگین در OpenCV

توجه: باز شدن در یک پنجره جدید. PDFچاپنامه الکترونیک

نوشته شده توسط مدیر سایت پنجشنبه 23 دی 1389 ساعت 18:58

خوشه یابی یکی از مباحث مطرح در حوزه شناسایی الگو است که به عنوان یک طبقه بند بدون نظارت (unsupervised classifier) هم شناخته می شود. وظیفه یک الگوریتم خوشه یابی این است که داده های ورودی را تحلیل کرده و آنها را به تعدادی خوشه تقسیم کند:

خوشه بندی به روش k میانگین

نقاط پراکنده در صفحه دوبعدی به 5 خوشه تقسیم شده اند.
یکی از معروفترین الگوریتمهای خوشه بندی، الگوریتم K میانگین (K-means یا C-means) است. این الگوریتم تلاش می کند که بر اساس یک معیار فاصله، داده ها را به k خوشه تقسیم کند. معمولا هر خوشه توسط بردار میانگین داده های موجود در آن نمایندگی می شود. در روش k همسایگی، روند کار به طور ساده به این صورت است که ابتدا K بردار تصادفی به عنوان مراکز خوشه های اولیه انتخاب می شوند. این بردارها می توانند از فضای داده های ورودی انتخاب شوند یا مقادیر کاملا تصادفی داشته باشند. سپس هر داده ورودی بر اساس یک معیار فاصله (مثل فاصله اقلیدسی یا city block) با بردارهای میانگین اولیه، به یکی از خوشه ها تخصیص داده می شود. در پایان دوره اول، میانگین خوشه ها بر اساس داده هایی که به هر خوشه تخصیص داده شده است، به روز می شوند و فرایند مقایسه و تخصیص تکرار می شود. این فرایند آنقدر ادامه می یابد که بردارهای میانگین خوشه ها دیگر تغییر نکند. تمام

پیاده سازی این الگوریتم خیلی ساده است و هر برنامه نویس متوسطی می تواند پیاده سازی کند لیکن کتابخانه OpenCV این الگوریتم را دارد و شما می توانید به راحتی از آن استفاده کنید.
کد زیر یک برنامه نمونه با استفاده از OpenCV است که البته در مثالهای خود OpenCV هم مشابه آن یافت می شود. جهت استفاده از ساختار جدید OpenCV تغییراتی در آن اعمال شده که استفاده آن در سایر برنامه ها را آسانتر کند. این برنامه چند خوشه با توزیع های گاوسی مختلف تولید می کند و سپس با الگوریتم kmeans آنها را خوشه یابی می کند و در قالب یک تصویر، نتیجه خوشه بندی را نمایش می دهد:
 
#ifdef _CH_
#pragma package 
#endif
 
#define CV_NO_BACKWARD_COMPATIBILITY
 
#ifndef _EiC
#include "cv.h"
#include "highgui.h"
#include 
#endif
 
#ifdef _DEBUG
#pragma comment (lib, "highguid.lib")
#pragma comment (lib, "cxcored.lib")
#else
#pragma comment (lib, "highgui.lib")
#pragma comment (lib, "cxcore.lib")
#endif
 
int main( int argc, char** argv )
{
#define MAX_CLUSTERS 5
	CvScalar color_tab[MAX_CLUSTERS];
	IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
	CvRNG rng = cvRNG(-1);
	CvPoint ipt;
 
	color_tab[0] = CV_RGB(255,0,0);
	color_tab[1] = CV_RGB(0,255,0);
	color_tab[2] = CV_RGB(100,100,255);
	color_tab[3] = CV_RGB(255,0,255);
	color_tab[4] = CV_RGB(255,255,0);
 
	cvNamedWindow( "clusters", 1 );
 
	for(;;)
	{
  char key;
  int k, cluster_count = cvRandInt(&rng)%MAX_CLUSTERS + 1;
  int i, sample_count = cvRandInt(&rng)%1000 + 1;
 
 
  cv::Mat _points (sample_count, 2, CV_32FC1);
  cv::Mat _clusters (sample_count, 1, CV_32SC1);
  //cv::RNG& rng = cv::theRNG();
  //rng.fill(_points, cv::RNG::NORMAL, param1, param2 );
  for(int i = 0; i < sample_count; i++){
   CvPoint center;
   CvMat point_chunk;
   center.x = cvRandInt(&rng)%img->width;
   center.y = cvRandInt(&rng)%img->height;
  }
 
  CvMat* points = cvCreateMat( sample_count, 1, CV_32FC2 );
  CvMat* clusters = cvCreateMat( sample_count, 1, CV_32SC1 );
  cluster_count = MIN(cluster_count, sample_count);
 
  /* generate random sample from multigaussian distribution */
  for( k = 0; k < cluster_count; k++ )
  {
   CvPoint center;
   CvMat point_chunk;
   center.x = cvRandInt(&rng)%img->width;
   center.y = cvRandInt(&rng)%img->height;
   cvGetRows( points, &point_chunk, k*sample_count/cluster_count,
    k == cluster_count - 1 ? sample_count :
    (k+1)*sample_count/cluster_count, 1 );
 
   cvRandArr( &rng, &point_chunk, CV_RAND_NORMAL,
    cvScalar(center.x,center.y,0,0),
    cvScalar(img->width*0.1,img->height*0.1,0,0));
  }
 
  /* shuffle samples */
  for( i = 0; i < sample_count/2; i++ )
  {
   CvPoint2D32f* pt1 = (CvPoint2D32f*)points->data.fl + cvRandInt(&rng)%sample_count;
   CvPoint2D32f* pt2 = (CvPoint2D32f*)points->data.fl + cvRandInt(&rng)%sample_count;
   CvPoint2D32f temp;
   CV_SWAP( *pt1, *pt2, temp );
  }
 
 
  for(int i = 0; i < sample_count; i++){   
   _points.at(i, 0) = points->data.fl[i*2];
   _points.at(i, 1) = points->data.fl[i*2+1];
  }
 
 
  //old OpenCV Style
  //cvKMeans2( points, cluster_count, clusters,
  //	cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0 ),
  //	5, 0, 0, 0, 0 );
 
  //New OpenCV Style
  cv::kmeans( _points, cluster_count, _clusters,
   cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0 ),
   5, 0, 0);
 
  cvZero( img );
 
  for( i = 0; i < sample_count; i++ )
  {
   //int cluster_idx = clusters->data.i[i];
   //ipt.x = (int)points->data.fl[i*2];
   //ipt.y = (int)points->data.fl[i*2+1];
 
   int cluster_idx = _clusters.at(i, 0);
   ipt.x = (int)_points.at (i, 0);
   ipt.y = (int)_points.at (i, 1);
 
   cvCircle( img, ipt, 2, color_tab[cluster_idx], CV_FILLED, CV_AA, 0 );
  }
 
  cvReleaseMat( &points );
  cvReleaseMat( &clusters );
 
  cvShowImage( "clusters", img );
 
  key = (char) cvWaitKey(0);
  if( key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
   break;
	}
 
	cvDestroyWindow( "clusters" );
	return 0;
}
 
#ifdef _EiC
main(1,"kmeans.c");
#endif
 
 
   

JPAGE_CURRENT_OF_TOTAL