نوشته‌ها

برای پی بردن به این موضوع که کدامیک از دو تکنولوژی CCD یا CMOS بهتر است و تصویر بهتری در اختیار کاربر قرار میدهد، لازم است تا ابتدا نحوه ی عملکرد هرکدام از این تکنولوژی ها را فرا بگیریم :

CCD چطور کار میکند ؟

نحوه کار CCD

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

CMOS چطور کار میکند ؟

نحوه کار CMOS

تفاوت اصلی تکنولوژی CMOS با CCD همانطور که در شکل کاملا مشخص می باشد در این است که فتودیودها و ترانزیستورها در تکنولوژی CMOS بر روی یک برد سوار میشوند.

این روش باعث پایین آمدن مصرف انرژی نسبت به CCD و کمترشدن قیمت تمام شده ی محصول تهیه شده با تکنولوژی CMOS می شود ولی با توجه به کیفیت پایین تر و حساسیت به نور کمتر نمیتوان گفت که دوربین هایی که از تکنولوژی CMOS استفاده میکنند کارایی بهتری نسبت به دوربین های مشابه با تکنولوژی CCD دارند.

تفاوت CCD و CMOS

مقایسه CCD با CMOS :

در شکل بالا تصاویر تهیه شده توسط دو دوربین با لنزها و شرایط نوردهی یکسان توسط CCD و CMOS نمایش داده شده است. همانطور که در شکل ملاحظه می فرمایید تصاویر تهیه شده با CCD از نویز کمتری برخوردار بوهد و رنگ ها شفافیت و واقعیت بیشتری دارند.

بطور کلی اگر بخواهیم این دو تکنولوژی را با هم مقایسه کنیم میتوانیم به موارد زیر توجه کنیم :
• دوربین های CMOS حساسیت به نور کمتری دارند، لذا تصاویر دریافت شده از کیفیت پایینتری نسبت به تکنولوژی همرده در دوربین های CCD برخوردار است.
• دوربین های CMOS حساسیت بیشتری به نویز دارند.
• دوربین های CMOS در هنگام استفاده از سیستم “دید در شب” چون از راهکار “مادون قرمز” استفاده میشود که نور تک رنگ با قدرت کم در محیط وجود دارد، تصاویر مناسبی ارائه نمیدهند.
• دوربین های CMOS ارزانتر از دوربین های CCD میباشند و این به دلیل عدم استفاده از یک بورد جداگانه برای عمل پردازش تصویر می باشد.
• دوربین های CMOS مصرف انرژی کمتری نسبت به دوربین های CCD دارند و درصورتی که شما از سیستم های امنیت تصویری با باتری یا سیستم پشتیبان ( یو پی اس ) استفاده میکنید بکاربردن دوربین های CMOS به صرفه تر است.
• قابلیت های دوربین های CMOS برای تشخیص چهره، حرکت و … پایین تر از دوربین های CCD می باشد.
• دوربین های CCD با سرعت بیشتری عمل Shuttering را انجام می دهند به این معنی که عمل تصویربرداری از اجسام متحرک بهتر و واضح تر انجام می شود.

منبع

چرا از فضای رنگی مختلف استفاده می کنیم؟

از فضای رنگی مختلف استفاده می کنیم چون این امکان در آن فضای رنگی به ما داده میشه تا بتوینم رنگ دلخواه مان را به راحتی از محدوده دیگر رنگ ها جدا کنیم .فرض کنید که شما قصد دارید رنگ سبز را در تصویر فیلتر نمایید این بازه شامل طیفی می باشد که یک سمت آن سبز تیره و در سمت دیگر آن سبز روشن می باشد برای جدا کردن آن در فضای رنگی RGB این امکان وجود ندارد که شما بتوان به صورت خطی یعنی هر کانال با یک شرط بازه رنگ دلخواه را انتخاب نمائید پس به خاطر چنین مشکلاتی تصویر را به فضای رنگی HSV انتقال می دهیم که این فضا از اجزای Hue (رنگدانه) ،Saturation(اشباع) و Value(روشنایی) تشکیل شده.برای تفکیک رنگ سبز در این فضای رنگی کافیست محدوده Hue خود که مربوط به رنگ مورد نظر را انتخاب کرده و سپس کل محدوه اشباع و در نهایت انتخاب محدوده دلخواه برای روشنایی پس در این فضای رنگی به راحتی تونستید رنگ دلخواه خودتون را انتخاب کنید.

تبدیل فضای رنگی در opencv

در کتابخانه Opencv می تونیم از تابع cvtColor استفاده کنیم.

مثال:


/*------------------------------------------------------------------------------------------*\
This file contains material supporting chapter 3 of the cookbook:
Computer Vision Programming using the OpenCV Library
Second Edition
by Robert Laganiere, Packt Publishing, 2013.

This program is free software; permission is hereby granted to use, copy, modify,
and distribute this source code, or portions thereof, for any purpose, without fee,
subject to the restriction that the copyright notice may not be removed
or altered from any source or altered source distribution.
The software is released on an as-is basis and without any warranties of any kind.
In particular, the software is not guaranteed to be fault-tolerant or free from failure.
The author disclaims all warranties with regard to this software, any use,
and any consequent failure, is purely the responsibility of the user.

Copyright (C) 2013 Robert Laganiere, www.laganiere.name
\*------------------------------------------------------------------------------------------*/

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <vector>

void detectHScolor(const cv::Mat& image, // input image
double minHue, double maxHue, // Hue interval
double minSat, double maxSat, // saturation interval
cv::Mat& mask) { // output mask

// convert into HSV space
cv::Mat hsv;
cv::cvtColor(image, hsv, CV_BGR2HSV);

// split the 3 channels into 3 images
std::vector<cv::Mat> channels;
cv::split(hsv, channels);
// channels[0] is the Hue
// channels[1] is the Saturation
// channels[2] is the Value

// Hue masking
cv::Mat mask1; // under maxHue
cv::threshold(channels[0], mask1, maxHue, 255, cv::THRESH_BINARY_INV);
cv::Mat mask2; // over minHue
cv::threshold(channels[0], mask2, minHue, 255, cv::THRESH_BINARY);

cv::Mat hueMask; // hue mask
if (minHue < maxHue)
hueMask = mask1 & mask2;
else // if interval crosses the zero-degree axis
hueMask = mask1 | mask2;

// Saturation masking
// under maxSat
cv::threshold(channels[1], mask1, maxSat, 255, cv::THRESH_BINARY_INV);
// over minSat
cv::threshold(channels[1], mask2, minSat, 255, cv::THRESH_BINARY);

cv::Mat satMask; // saturation mask
satMask = mask1 & mask2;

// combined mask
mask = hueMask&satMask;
}

int main()
{
// read the image
cv::Mat image= cv::imread("boldt.jpg");
if (!image.data)
return 0;

// show original image
cv::namedWindow("Original image");
cv::imshow("Original image",image);

// convert into HSV space
cv::Mat hsv;
cv::cvtColor(image, hsv, CV_BGR2HSV);

// split the 3 channels into 3 images
std::vector<cv::Mat> channels;
cv::split(hsv,channels);
// channels[0] is the Hue
// channels[1] is the Saturation
// channels[2] is the Value

// display value
cv::namedWindow("Value");
cv::imshow("Value",channels[2]);

// display saturation
cv::namedWindow("Saturation");
cv::imshow("Saturation",channels[1]);

// display hue
cv::namedWindow("Hue");
cv::imshow("Hue",channels[0]);

// image with fixed value
cv::Mat newImage;
cv::Mat tmp(channels[2].clone());
// Value channel will be 255 for all pixels
channels[2]= 255;
// merge back the channels
cv::merge(channels,hsv);
// re-convert to BGR
cv::cvtColor(hsv,newImage,CV_HSV2BGR);

cv::namedWindow("Fixed Value Image");
cv::imshow("Fixed Value Image",newImage);

// image with fixed saturation
channels[1]= 255;
channels[2]= tmp;
cv::merge(channels,hsv);
cv::cvtColor(hsv,newImage,CV_HSV2BGR);

cv::namedWindow("Fixed saturation");
cv::imshow("Fixed saturation",newImage);

// image with fixed value and fixed saturation
channels[1]= 255;
channels[2]= 255;
cv::merge(channels,hsv);
cv::cvtColor(hsv,newImage,CV_HSV2BGR);

cv::namedWindow("Fixed saturation/value");
cv::imshow("Fixed saturation/value",newImage);

// Testing skin detection

// read the image
image= cv::imread("girl.jpg");
if (!image.data)
return 0;

// show original image
cv::namedWindow("Original image");
cv::imshow("Original image",image);

// detect skin tone
cv::Mat mask;
detectHScolor(image,
۱۶۰, ۱۰, // hue from 320 degrees to 20 degrees
۲۵, ۱۶۶, // saturation from ~0.1 to 0.65
mask);

// show masked image
cv::Mat detected(image.size(), CV_8UC3, cv::Scalar(0, 0, 0));
image.copyTo(detected, mask);
cv::imshow("Detection result",detected);

// A test comparing luminance and brightness

// create linear intensity image
cv::Mat linear(100,256,CV_8U);
for (int i=0; i<256; i++) {

linear.col(i)= i;
}

// create a Lab image
linear.copyTo(channels[0]);
cv::Mat constante(100,256,CV_8U,cv::Scalar(128));
constante.copyTo(channels[1]);
constante.copyTo(channels[2]);
cv::merge(channels,image);

// convert back to BGR
cv::Mat brightness;
cv::cvtColor(image,brightness, CV_Lab2BGR);
cv::split(brightness, channels);

// create combined image
cv::Mat combined(200,256, CV_8U);
cv::Mat half1(combined,cv::Rect(0,0,256,100));
linear.copyTo(half1);
cv::Mat half2(combined,cv::Rect(0,100,256,100));
channels[0].copyTo(half2);

cv::namedWindow("Luminance vs Brightness");
cv::imshow("Luminance vs Brightness",combined);

cv::waitKey();
}

منبع

راه اندازی کانال شرکت بهسان اندیش در تلگرام و سایر پیام رسان ها

کانال شرکت بهسان اندیش در تلگرام و سایر پیام رسان ها– در دنیای مجازی که شبکه های اجتماعی همچون کشوری مستقل عمل می کنند دسته ای از کاربران متناسب با فعالیت خود نیاز به امکاناتی خاص تر دارند. سازمان های دولتی و خصوصی، برند ها، شخصیت های سیاسی، هنری، فرهنگی و… برای ایجاد ارتباط و پیشبرد فعالیت خود نیاز به اعتماد مخاطب دارند.

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

شرکت بهسان اندیش به منظور ارائه خدمات و فعالیت های خود در شبکه های اجتماعی اقدام به راه اندازی کانال شرکت بهسان اندیش در تلگرام و پیام رسان های داخلی نموده که علاقمندان می توانند از طریق لینک زیر در این پیام رسان ها ما را دنبال کنید:

? پیام رسان تلگرام (مرکز اصلی اطلاع رسانی شرکت) :

https://t.me/Behsan_Transit

 

? در سروش (با اینترنت نیم بها) :
sapp.ir/behsanandish

 

? در ایتا (با محیطی کاملا مشابه تلگرام) :
eitaa.com/behsanandish

 

کار با Thread ها در زبان سی شارپ :: آشنایی با مشکل Concurrency در برنامه های Multi-Threaded و راهکار های رفع این مشکل

زمانی که ما برنامه های Multi-Threaded می نویسیم، برخی اوقات Thread های ایجاد شده به داده های مشترک در سطح برنامه دسترسی دارند و وظیفه ما به عنوان برنامه نویس این است که مطمئن باشیم دسترسی چند Thread به داده های مشترک باعث بروز مشکل نمی شود. برای آشنایی بیشتر با این موضوع شرایطی را در نظر بگیرید که یک متد قرار است در چندین thread مختلف به صورت جداگانه اجرا شود، بعد از شروع کار هر thread زمانبندی اجرا توسط CLR به هر thread به صورت خودکار انجام شده و ما نمی توانیم دخالتی در این موضوع داشته باشیم، ممکن است در این بین اختصاص زمان به یک thread بیش از thread دیگر انجام شود و در این بین خروجی مناسب مد نظر ما ایجاد نمی شود. برای آشنایی با این موضوع متد PrintNumbers که در زیر تعریف کردیم را در نظر بگیرید:

public static void PrintNumbers()
{
    Console.Write("{0} is printing numbers  >  " , Thread.CurrentThread.Name);
    for (int counter = 0; counter  <  10 ;  counter++)
    {
        Thread.Sleep(200*new Random().Next(5));
        Console.Write("{0},", counter);
    }
    Console.WriteLine();
}

در مرحله بعد متد Main را به صورت زیر تغییر می دهیم تا ۱۰ thread ایجاد شده و سپس کلیه thread ها اجرا شوند:

Thread[] threads = new Thread[10];

for (int index = 0; index  <  10 ;  index++)
{
    threads[index] = new Thread(PrintNumbers);
    threads[index].Name = string.Format("Worker thread #{0}.", index);
}

foreach (var thread in threads)
{
    thread.Start();
}

Console.ReadLine();

همانطور که مشاهده می کنید کلیه thread ها به صورت همزمان اجرا می شوند، اما پس از اجرا کد بالا، خروجی برای بار اول به صورت خواهد بود، البته دقت کنید که با هر بار اجرا خروجی تغییر می کند و ممکن است برای بار اول خروجی زیر برای شما تولید نشود:

Worker thread #0. is printing numbers  >  Worker thread #1. is printing numbers  >  Worker thread #2. is printing numbers  >  Worker thread #3. is printing numbers  >  0,Worker thread #4. is printing numbers  >  0,1,1,2,3,2,Worker thread #5. is printing numbers  >  0,4,3,1,4,2,5,Worker thread #6. is printing numbers  >  5,3,Worker thread #7. is printing numbers  >  4,6,6,0,Worker thread #8. is printing numbers  >  Worker thread #9. is printing numbers  >  0,0,7,5,7,0,1,0,1,0,6,8,8,1,2,1,1,0,2,9,
۷,۳,۲,۲,۹,
۲,۱,۸,۳,۳,۳,۴,۲,۱,۹,
۴,۴,۴,۵,۳,۳,۵,۵,۵,۶,۲,۶,۶,۷,۶,۴,۴,۷,۷,۸,۹,
۸,۹,
۷,۸,۹,
۵,۵,۳,۸,۶,۷,۸,۹,
۶,۷,۸,۹,
۴,۵,۹,
۶,۷,۸,۹,

اگر برنامه را مجدد اجرا کنید خروجی متفاوتی از خروجی قبلی دریافت خواهیم کرد:

Worker thread #0. is printing numbers  >  Worker thread #1. is printing numbers  >  Worker thread #2. is printing numbers  >  Worker thread #3. is printing numbers  >  Worker thread #4. is printing numbers  >  Worker thread #5. is printing numbers  >  Worker thread #6. is printing numbers  >  0,Worker thread #7. is printing numbers  >  1,2,0,1,3,2,4,3,Worker thread #8. is printing numbers  >  Worker thread #9. is printing numbers  >  0,0,0,0,0,0,5,4,5,6,7,8,9,
۶,۷,۸,۹,
۱,۱,۰,۰,۱,۱,۱,۱,۱,۱,۲,۲,۲,۲,۲,۲,۲,۲,۳,۳,۳,۴,۵,۶,۷,۸,۹,
۳,۳,۳,۳,۳,۴,۴,۴,۴,۵,۶,۷,۸,۹,
۵,۶,۷,۸,۹,
۵,۶,۷,۵,۶,۷,۸,۹,
۸,۴,۴,۴,۵,۵,۶,۶,۷,۷,۹,
۵,۸,۸,۶,۹,
۹,
۷,۸,۹,

همانطور که مشاهده می کنید خروجی های ایجاد کاملاً با یکدیگر متفاوت هستند. مشخص است که در اینجا مشکلی وجود دارد و همانطور که در ابتدا گفتیم این مشکل وجود همزمانی یا Concurrency در زمان اجرای thread هاست. زمابندی CPU برای اجرای thread ها متفاوت است و با هر بار اجرا زمان های متفاوتی به thread ها برای اجرا تخصیص داده می شود. اما خوشبختانه مکانیزم های مختلفی برای رفع این مشکل و پیاده سازی Synchronizqation وجوددارد که در ادامه به بررسی راهکاری های مختلف برای حل مشکل همزمانی می پردازیم.

پیاده سازی Synchronization با کلمه کلیدی lock

اولین مکانیزم مدیریت همزمانی در زمان اجرای Thread ها استفاده از کلمه کلیدی lock است. این کلمه کلیدی به شما این اجازه را می دهد تا یک scope مشخص کنید که این scope باید به صورت synchronized بین thread ها به اشتراک گذاشته شود، یعنی زمانی که یک thread وارد scope ای شد که با کلمه کلیدی lock مشخص شده، thread های دیگر باید منتظر شوند تا thread جاری که در scope قرار دارد از آن خارج شود. برای استفاده از lock شما اصطلاحاً می بایست یک token را برای scope مشخص کنید که معمولاً این کار با ایجاد یک شئ از نوع object و مشخص کردن آن به عنوان token برای synchronization استفاده می شود. شیوه کلی استفاده از lock به صورت زیر است:

lock(token)
{
    // all code in this scope are thread-safe
}

اصطلاحاً می گویند کلیه کدهایی که در بدنه lock قرار دارند thread-safe هستند. برای اینکه کد داخل متد PrintNumbers به صورت thread-safe اجرا شود، ابتدا باید یک شئ برای استفاده به عنوان token در کلاس Program تعریف کنیم:

class Program
{
    public static object threadLock = new object();

    ....

در قدم بعدی کد داخل متد PrintNumbers را به صورت زیر تغییر می دهیم:

public static void PrintNumbers()
{
    lock (threadLock)
    {
        Console.Write("{0} is printing numbers  >  " , Thread.CurrentThread.Name);
        for (int counter = 0; counter  <  10 ; counter++)
        {
            Thread.Sleep(200 * new Random().Next(5));
            Console.Write("{0},", counter);
        }
        Console.WriteLine();
    }
}

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

Worker thread #0. is printing numbers  >  0,1,2,3,4,5,6,7,8,9,
Worker thread #1. is printing numbers  >  0,1,2,3,4,5,6,7,8,9,
Worker thread #2. is printing numbers  >  0,1,2,3,4,5,6,7,8,9,
Worker thread #3. is printing numbers  >  0,1,2,3,4,5,6,7,8,9,
Worker thread #4. is printing numbers  >  0,1,2,3,4,5,6,7,8,9,
Worker thread #5. is printing numbers  >  0,1,2,3,4,5,6,7,8,9,
Worker thread #6. is printing numbers  >  0,1,2,3,4,5,6,7,8,9,
Worker thread #7. is printing numbers  >  0,1,2,3,4,5,6,7,8,9,
Worker thread #8. is printing numbers  >  0,1,2,3,4,5,6,7,8,9,
Worker thread #9. is printing numbers  >  0,1,2,3,4,5,6,7,8,9,

پیاده سازی Synchronization بوسیله کلاس Monitor

در قسمت قبل که از کلمه کلیدی lock استفاده کردیم، در حقیقت به در پشت زمینه از کلاس Monitor که در فضای نام System.Threading قرار دارد استفاده شده است. زمانی که از کلمه کلیدی lock استفاده می کنیم این کد تبدیل به کدی می شود که از Monitor برای پیاده سازی Synchronization استفاده می کند (می توان این موضوع را با ابزار ildasm.exe و مشاهده کد IL متوجه شد). نحوه استفاده از کلاس Mutex را در کد زیر که تغییر داده شده متد PrintNumbers است مشاهده می کنید:

public static void PrintNumbers()
{
    Monitor.Enter(threadLock);            
    try
    {
        Console.Write("{0} is printing numbers  >  " , Thread.CurrentThread.Name);
        for (int counter = 0; counter  <  10 ; counter++)
        {
            Thread.Sleep(200*new Random().Next(5));
            Console.Write("{0},", counter);
        }
        Console.WriteLine();
    }
    finally
    {
        Monitor.Exit(threadLock);
    }
}

متد Enter در کلاس Monitor اعلام می کند که thread ای وارد محدوده ای شده است که باید thread-safe باشد. به عنوان پارامتر ورودی برای این متد token ایجاد شده یعنی obj را ارسال می کنیم. در قدم بعدی کل کدی که مربوط به ناحیه thread-safe است باید داخل بدنه try-catch نوشته شود و البته بخش finaly نیز برای آن نوشته شده باشد، همانطور که می دانید بخش finally قسمتی از بدنه try است که در هر صورت اجرا می شود. در قسمت finally متد Exit را با پارامتر threadLock که همان token مربوطه است فراخوانی می کنیم، یعنی thread در حال اجرا از محدوده thread-safe خارج شده است. دلیل نوشتن try-catch در کد بالا این است که در صورت وقوع خطا عملیات خروج از محدوده thread-safe در هر صورت انجام شود و thread های دیگر منتظر ورود به این محدوده نمانند. شاید این سوال برای شما بوجود بیاید که با وجود کلمه کلیدی lock چه دلیلی برای استفاده از کلاس Monitor وجود دارد؟ دلیل این موضوع کنترل بیشتر بر روی ورود thread ها و اجرای کدهای thread-safe است. برای مثال، بوسیله متد Wait در کلاس Monitor می توان مشخص کرد که یک thread چه مدت زمانی را برای ورود به ناحیه thread-safe باید منتظر بماند و همچنین متدهای Pulse و PulseAll را می توان برای اطلاع رسانی به سایر thread ها در مورد اینکه کار thread جاری به اتمام رسیده استفاده کرد. البته در اکثر موقعیت ها استفاده از کلمه کلیدی lock کافی است و نیازی به استفاده از کلاس Monitor نمی باشد.

پیاده سازی Synchronization با استفاده از کلاس Interlocked

زمانی که قصد داریم مقدار یک متغیر را تغییر دهیم یا عملگرهای ریاضی را بر روی دو متغیر اعمال کنیم، عملیات های انجام شده به دو صورت Atomic و Non-Atomic انجام می شوند. مبحث عملیات عملیات های Atomic چیزی بیش از چند خط نیاز دارد تا توضیح داده شود، اما به طور خلاصه می توان گفت که عملیات های Atomic عملیات هایی هستند که تنها در یک مرحله یا step انجام می شوند. اگر کدهای IL مرتبط به مقدار دهی متغیرها و البته عملگرهای ریاضی را بر روی بیشتر نوع های داده در دات نت مشاهده کنیم میبینیم که این عملیات ها بیشتر به صورت non-atomic هستند، یعنی بیش از یک مرحله برای انجام عملیات مربوط نیاز است که این موضوع می تواند در برنامه های Multi-threaded مشکل ساز شود. در حالت ساده می توان بوسیله مکانیزم lock عملیات synchronization را برای این عملیات ها پیاده سازی کرد:

int value = 1;
lock(token)
{
    value++;
}

اما برای شرایطی مانند مثال بالا استفاده از lock یا کلاس monitor باعث ایجاد overhead اضافی می شود که برای حل این مشکل می توان از کلاس Interlocked برای اعمال synchronization در اعمال انتساب مقدار یا مقایسه مقادیر استفاده کرد. برای مثال، زمانی که می خواهیم مقدار یک متغیر را با استفاده از کلاس Interlocked اضافه کنیم به صورت می توانیم این کار را پیاده سازی کنیم:

int myNumber = 10;
Interlocked.Increment(ref myNumber);

متد Increment در کلاس Interlocked یک مقدار به متغیر مشخص شده اضافه می کند و البته این کار در محیط Thread-Safe انجام می شود. برای کاهش مقدار می توان از متد Decrement به صورت مشابه استفاده کرد:

int myNumber = 10;
Interlocked.Decrement(ref myNumber);

همچنین برای مقایسه و مقدار دهی مقدار یک متغیر می توان از متد CompareExchange استفاده به صورت زیر استفاده کرد:

int myNumber = 10;
Interlocked.CompareExchange(ref myNumber, 15, 10);

در کد بالا در صورتی که مقدار متغیر myNumber برابر ۱۰ باشد، مقدار آن با ۱۵ عوض خواهد شد.

پیاده سازی Synchronization بوسیله خاصیت [Synchronization]

می دانیم که خاصیت [Synchronization] زمانی که بر روی یک کلاس قرار میگیرد، باعث می شود که کد داخل آن کلاس به صورت Thread-Safe اجرا شود. در این قسمت می خواهیم کد مربوط به متد PrintNumbers را به صورت Thread-Safe و با کمک Object Context Boundry و همچنین خاصیت [Synchronization] پیاده سازی کنیم. برای این کار ابتدا یک کلاس با نام Printer پیاده سازی کرده و متد PrintNumbers را داخل آن قرار می دهیم. دقت کنید که کلاس Printer می بایست از کلاس ContextBoundObject مشتق شده باشد و خاصیت [Synchronization] بر روی آن قرار گرفته باشد:

[Synchronization]
public class Printer : ContextBoundObject
{
    public void PrintNumbers()
    {
        Console.Write("{0} is printing numbers  >  " , Thread.CurrentThread.Name);
        for (int counter = 0; counter  <  10 ; counter++)
        {
            Thread.Sleep(200*new Random().Next(5));
            Console.Write("{0},", counter);
        }
        Console.WriteLine();
    }
}

پس از انجام تغییرات بالا متد Main را به صورتی تغییر می دهیم که از متد Print در کلاس Printer استفاده کند:

Printer printer = new Printer();

Thread[] threads = new Thread[10];

for (int index = 0; index  <  10 ; index++)
{
    threads[index] = new Thread(printer.PrintNumbers);
    threads[index].Name = string.Format("Worker thread #{0}.", index);
}

foreach (var thread in threads)
{
    thread.Start();
}

Console.ReadLine();

با انجام کارهای بالا و اجرای برنامه مشاهده خواهیم کرد که با وجود عدم استفاده از کلمه کلیدی lock یا کلاس Monitor، برنامه به صورت Thread-Safe اجرا شده و خروجی مناسب برای ما تولید می شود. در اینجا مبحث مربوط به Synchronization به اتمام رسیده و در قسمت در مورد کلاس Timer در فضای نام System.Threading صحبت خواهیم کرد.

منبع


قسمت اول آموزش-برنامه نویسی Asynchronous – آشنایی با Process ها، Thread ها و AppDomain ها

قسمت دوم آموزش- آشنایی با ماهیت Asynchronous در Delegate ها

قسمت سوم آموزش-آشنایی با فضای نام System.Threading و کلاس Thread

قسمت چهارم آموزش- آشنایی با Thread های Foreground و Background در دات نت

قسمت پنجم آموزش- آشنایی با مشکل Concurrency در برنامه های Multi-Threaded و راهکار های رفع این مشکل

قسمت ششم آموزش- آشنایی با کلاس Timer در زبان سی شارپ

قسمت هفتم آموزش-آشنایی با CLR ThreadPool در دات نت

قسمت هشتم آموزش- مقدمه ای بر Task Parallel Library و کلاس Parallel در دات نت

قسمت نهم آموزش- برنامه نویسی Parallel:آشنایی با کلاس Task در سی شارپ

قسمت دهم آموزش-برنامه نویسی Parallel در سی شارپ :: متوقف کردن Task ها در سی شارپ – کلاس CancellationToken

قسمت یازدهم آموزش- برنامه نویسی Parallel در سی شارپ :: کوئری های Parallel در LINQ

قسمت دوازدهم آموزش- آشنایی با کلمات کلیدی async و await در زبان سی شارپ

قسمت سیزدهم آموزش- استفاده از متد WhenAll برای اجرای چندین Task به صورت همزمان در سی شارپ

ویژگی‌های جدید در سی شارپ  ۳٫۰

این ورژن از سی شارپ در تاریخ ۱۹ نوامبر سال ۲۰۰۷ به عنوان بخشی از چارچوب دات‌نت ۳٫۵ عرضه شد؛ که شامل ویژگی‌های جدید الهام شده از زبان‌های برنامه‌نویسی اصلی (Functional) مانند Haskell و ML، و الگوی LINQ برای CLR است. در حال حاضر توسط هیچ موسسه استانداردسازی تأیید نشده‌است.

معرفی لینک

لینک (به انگلیسی: Language Integrated Query)(مخفف انگلیسی: LINQ) یک زبان پرس و جوی قابل انعطاف و همه منظوره برای بسیاری از انواع منبع داده‌ها است (مثل انتخاب اشیاء شناور، سندهای XML، بانک‌های اطلاعاتی و…) که در ویژگی‌های سی شارپ ۳ جمع شده‌اند. سینتکس زبان به زحمت از SQL گرفته شده‌است، برای مثال:

int[] array = { 1, 5, 2, 10, 7 };

// Select squares of all odd numbers in the array sorted in descending order
IEnumerable&lt;int&gt; query = from x in array
                         where x % 2 == 1
                         orderby x descending
                         select x * x;

مقدار دهی به اشیاء

Customer c = new Customer(); c.Name = "James";

عبارت بالا می‌تواند به صورت زیر نوشته شود:

Customer c = new Customer { Name="James" };

مقدار دهی Collection

MyList list = new MyList();
list.Add(1);
list.Add(2);

عبارت بالا می‌تواند به صورت زیر نوشته شود:

MyList list = new MyList { 1, 2 };

فرض کنید که اجزای MyList و System.Collections.IEnumerable دارای متد عمومی Add هستند.

انواع داده‌ای بی نام

var x = new { FirstName="James", LastName="Frank" };

سی شارپ ۲٫۰ توابع بی نام را معرفی کرد. سی شارپ ۳٫۰ هم انواع بی نام را معرفی می‌کند. با استفاده از این ویژگی برنامه نویسان قادر خواهند بود به صورت Inline انواع دلخواه خود را ایجاد کنند. به نمونه زیر توجه کنید:

static void Main(string[] args)
{
    var anonymousType = new { Name = string.Empty, Age = 0 };
}

کد ارائه شده، یک نوع بی نام را تعریف می‌کند که از طریق متغیر ضمنی محلی به نام anonymousType در اختیار قرار می‌گیرد.

چرا Anonymous types؟ انواع بی نام بهترین گزینه برای تولید Entity Typeها می‌باشند. همان‌طور که گفته شد Entity Typeها فقط حاوی داده‌ها هستند؛ بنابراین به بهترین نحو می‌توان داده‌های دریافت شده از کاربر را در انواع بی نام بسته‌بندی کرد.

نتیجه نوع متغیر محلی

var x = new Dictionary < string, List < float >> ();

کد بالا با کد زیر قابل تعویض می‌باشد:

Dictionary < string, List < float >> x = new Dictionary < string, List < float >> ();

این ویژگی تنها یک ntactic sugarراحت برای کوتاه‌تر بیان کردن متغیرهای محلی نمی‌باشد، بلکه برای تعریف متغیرهای بی نام لازم نیز است.

عبارات لامبدا

عبارات لامبدا یک راه کوتاه برای نوشتن مقادیر توابع بی نام کلاس اول را فراهم می‌کنند. دو مثال زیر را در نظر بگیرید:

listOfFoo.Where(delegate(Foo x) { return x.Size > 10; })
listOfFoo.Where(x = > x.Size > 10);

در مثال‌های فوق، عبارات لامبدا صرفاً یک نوع سینتکس برای delegateهای بی نام با مقادیر دارای بازگشت هستند. هر چند با توجه به نوع متن استفاده می‌شوند، کامپایلر سی شارپ می‌تواند لامبداها را به ASTها نیز تبدیل کند تا بعداً در زمان اجرا نیز بتوانند پردازش شوند. در مثال فوق، اگر listOfFoo یک مجموعه ساده داخل حافظه نباشد، ولی یک پوشه در اطراف جدول بانک اطلاعاتیمی‌باشد. این تکنیک می‌تواند برای بهینه کردن اجرا، برای ترجمه بدنه لامبدا به عبارت معادل آن در SQL استفاده شود. در هر یک از دو راه فوق، خود عبارت لامبدا دقیقاً شبیه کد به نظر می‌رسد، بنابراین روش استفاده در زمان اجرا، برای کاربر ناپیدا می‌باشد.

یکی از ویژگی‌هایی که سی شارپ ۲٫۰ ارائه کرد، توانایی تعریف توابع به صورت Inline بود که این ویژگی با عنوان توابع بی نام (anonymous methods) شناخته می‌شود. توابع بی نام در پاره‌ای مواقع بسیار مفیدند. اما نحو(syntax) به‌کارگیری آن‌ها دشوار می‌باشد. عبارات لامبدا ویژگی توابع بی نام را دارند اما با نحو ساده‌تری در سی شارپ ۳٫۰ معرفی شده‌اند. به نمونه زیر توجه کنید:

static void Main(string[] args)
{
   (int x) = > x + 1;// explicitly typed parameter
   (y, z) = > y * z;// implicitly typed parameter
}

تعریف عبارات لامبدا از نحو (syntax) خاصی پیرو می‌کند. همان‌طور که در کد بالا مشاهده می‌کنید، پارامترهای تابع هم به صورت صریح و هم به صورت ضمنی قابل بیان‌اند. کلمه return به صورت ضمنی حذف شده‌است. تابع معادل عبارت لامبدای اول به صورت زیر است:

int Fn(int x)
{
    return x+1;
}

لیست پارامترها و بدنه عبارت لامبدا توسط => از هم جدا می‌شوند. در صورتی که تعریف عبارت لامبدا بیشتر از یک خط کد باشد می‌توان بدنه آن را با استفاده از {} نشان داد.

static void Main(string[] args)
{
    (int x) = > { x + 1; return x * x; };
}

خواص خودکار

کامپایلر به‌طور خودکار یک متغیر نمونه خصوصی و قرار دهنده و قرار گیرنده مناسب تولید می‌کند، مانند:

public string Name { get; private set; }

توابع بسط داده شده

توابع بسط داده شده حالتی از سینتکس Suger هستند که امکان اضافه کردن متد جدید به کلاس موجود را بیرون از حوزه تعریف آن فراهم می‌کنند. در این مثال، تابع بسط داده شده یک تابع ایستا است که قابل فراخوانی توسط تابع مشابه می‌باشد. گیرنده فراخوانی مقید به اولین پارامتر تابع تحت عنوان this می‌باشد:

public static class StringExtensions
{
    public static string Left(this string s, int n)
    {
        return s.Substring(0, n);
    }
}

string s = "foo";
s.Left(3);// same as StringExtensions.Left(s, 3);

زبان سی شارپ کلمه کلیدی sealed را برای این منظور ارائه کرد که امکان ارث بری از یک کلاس را صلب کند. یعنی با اضافه شدن این کلمه کلیدی به ابتدای تعریف کلاس، امکان ارث بری از آن غیرممکن می‌شود. سی شارپ ۳٫۰ ویژگی جدیدی را در اختیار برنامه نویسان قرار می‌دهد به این صورت که می‌توان هر نوع کلاسی حتی کلاس‌های مهر شده با Sealed را با استفاده از Extension methodsبسط داد.

توابع جزئی

توابع جزئی به تولیدکننده‌های کد اجازه تولید اعلان توابع به صورت نقاط گسترش یافته‌ای که تنها شامل کدهای اصلی هستند را می‌دهد، در صورتی که یک نفر آن را در قسمتی از کلاسی دیگر اجرا کند.

آرایه‌های نوع ضمنی

آرایه‌ها را نیز می‌توان با استفاده از کلمه کلیدی var تعریف کرد.

static void Main(string[] args)
{
    var a = new[] { 1, 10, 100, 1000 };// int[]
    var b = new[] { 1, "one", 2 };// Error
}

پیش پردازنده

ویژگی «دستورها پیش پردازنده» سی شارپ (اگرچه آن‌ها به واقع یک پیش پردازنده نیستند) مبنی بر دستورها پیش پردازنده C است که به برنامه‌نویس اجازه تعریف سمبلهایی را می‌دهند. برخی از این دستورها عبارتند از: #if، #region، #define. راهنماهایی نظیر #region تذکراتی به ویرایش‌گرها برای code folding می‌دهند.

توضیحات کد

توضیحات تک خط با استفاده از دو اسلش تعریف می‌شوند(//) و توضیحات چند خطی با /* شروع و به */ تمام می‌شوند.

public class Foo
{
// a comment
    public static void Bar(int firstParam) {}//Also a comment
}

public class FooBar
{
    /* a comment */
    public static void BarFoo(int firstParam) {}  /* Also a comment */

توضیحات چند خطی هم چنین می‌توانند با /* شروع و با */ تمام شوند.

public class Foo
{
    /* A Multi-Line
       comment  */
    public static void Bar(int firstParam) {}
}

سامانه مستندسازی XML

سامانه مستندسازی #C بسیار شبیه به جاوا است، اما مبنی بر XML. دو شیوه مستندسازی در حال حاضر به وسیله کامپایلر #C پشتیبانی می‌شود.

توضیحات تک خطی، که معمولاً در تولیدکننده کد Visual Studioپیدا می‌شوند، با استفاده از/// شروع می‌شوند.

public class Foo
{
/// < summary > A summary of the method. < /summary >
/// < param name="firstParam" > A description of the parameter. < /param >
/// < remarks > Remarks about the method. < /remarks >
    public static void Bar(int firstParam) {}
}

توضیحات چند خطی، که در نسخه ۱٫۰ تعریف شدند، اما در نسخه ۱٫۱ پشتیبانی از آن‌ها وجود نداشت با /* شروع و به */ ختم می‌شوند:

public class Foo
{
    /** < summary > A summary of the method. < /summary >
     *  < param name="firstParam" > A description of the parameter. < /param >
     *  < remarks>Remarks about the method. < /remarks > */
    public static void Bar(int firstParam) {}
}

نکته:در اینجا یک ملاک سخت در مورد استفاده از فضاهای خالی در سندهای XML هنگام استفاده از /**وجود دارد:

/**
 * < summary >
 * A summary of the method. < /summary > */

نوع دیگری از کد بالا ارائه خواهد شد:

/**
 * < summary >
   A summary of the method. < /summary > */

سینتکس سندسازی توضیحات XML در یک ضمیمه بی قاعده از استاندارد ECMA از سی شارپ وجود دارد. یک استاندارد مشابه قوانینی برای پردازش توضیحات و تبدیل آن‌ها به متون Plain در XML را با کمک قوانین CLI فراهم می‌کند. این به هر IDE در سی شارپ و دیگر ابزار گسترش دهنده امکان پیدا کردن هر نمادی را در کدها می‌دهد.

(CLR(Common Language Runtime

بخش مرکزی چارچوب دات‌نت، محیط اجرایی Runtime می‌باشد که اصطلاحاً به آن CLR یا .NET Runtime می‌گویند. کدهایی که تحت کنترل CLR اجرا می‌شوند اغلب به عنوان کدهای مدیریت شده نامیده می‌شوند.

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

  1. کامپایل سورس کد به MSIL.
  2. کامپایل MSIL به کد مختص پلتفرم به وسیله CLR

یک نکته قابل توجه، اشتراک زبان میانی مایکروسافت با کد بایت جاوا(Bytecode)است. ایده این اشتراک از آنجا سرچشمه گرفت که چون Bytecode یک زیان سطح پایین با یک دستور زبان ساده می‌باشد (که به جای متن مبتنی بر کدهای عددی است)، می‌تواند به سرعت به کدهای بومی(Native) ترجمه شود.

برخی ویژگی‌های MSIL

  • شیءگرایی و بکارگیری واسط‌ها
  • تمایز فراوان بین انواع مقداری و ارجاعی
  • تعیین Strong Type (این نوع داده دیگر معتبر نیست)
  • مدیریت خطا از طریق به‌کارگیری Exception
  • بکارگیری صفات

 

منبع

 

آشنایی با #C قسمت ۱
آشنایی با #C قسمت ۲
آشنایی با #C قسمت ۳

مقالات پردازش تصویر عبارت اند از:

Basics of digital image processing

مفاهیم اولیه پردازش تصویر

فایل PDF – در ۵۷ صفحه – نویسنده : ناشناس

Basics of digital image processing

پسوردفایل : behsanandish.com


Digital Image Processing Laboratory Manual

کتابچه راهنمای آزمایشگاه پردازش تصویر دیجیتال

فایل PDF – در ۱۹ صفحه – نویسنده :  Bhaskar Mondal

Digital Image Processing laboratory manual

پسوردفایل : behsanandish.com


Fundamentals of Digital Image Processing

اصول پردازش تصویر دیجیتال

فایل PDF – در ۸ صفحه – نویسنده : ناشناس

Fundamentals of Digital Image Processing

پسوردفایل : behsanandish.com


Fundamentals of Image Processing

اصول پردازش تصویر

فایل PDF – در ۱۱۲ صفحه – نویسنده : Ian T. Young , Jan J. Gerbrands  , Lucas J. van Vliet

Image Processing Fundamentals–An Overview

پسوردفایل : behsanandish.com


Image Processing Manual

دستورالعمل پردازش تصویر

فایل PDF – در ۱۶۴ صفحه – تهیه کننده : انستیتو ملی اسناد آمریکا

Image processing manual

پسوردفایل : behsanandish.com


Image Processing Tutorial-Basic Concepts 

آموزش پردازش تصویر-مفاهیم پایه

فایل PDF – در ۵۵ صفحه – تهیه کننده : شرکت CCDWare Publishing

Image Processing Tutorial

پسوردفایل : behsanandish.com


Intel® Image Processing Library-Reference Manual

کتابخانه پردازش تصویر اینتل-دستورالعمل مرجع

فایل PDF – در ۳۱۹ صفحه – نویسنده :  شرکت Intel

Intel Image Processing Library-reference manual

پسوردفایل : behsanandish.com


آنالیز و پردازش تصویر

فایل Word – در ۱۵ صفحه – نویسنده :  ناشناس

pardazesh tasvir

پسوردفایل : behsanandish.com


مفاهیم پایه پردازش تصویر-محیط های چند رسانه ای

فایل PDF – در ۱۰۹ صفحه – نویسنده :  احمد محمودی ازناوه (دانشگاه شهید بهشتی)

مفاهیم_پایه_پردازش_تصویر_دانشگاه

پسوردفایل : behsanandish.com

تاریخچه سیستمهای OCR

از جنبه تاریخی سیستم های OCR تا کنون سه مرحله تکاملی را پشت سر گذاشته اند:

ﺍﻟﻒ ) ﻣﺮحله ﺗﻜﻮﻳﻦ : (از سال ۱۹۰۰ تا ۱۹۸۰)

ﺭﺩ ﭘﺎﻱ ﺍﻭﻟﻴﺔ ﺍﻗﺪﺍﻣﺎﺕ ﺻﻮﺭﺕ ﮔﺮﻓﺘﻪ ﺩﺭ ﺯﻣﻴﻨﺔ ﺑﺎﺯﺷﻨﺎﺳﻲ حروف را ﺩﺭ ﺳﺎﻟﻬﺎﻱ ﺍﻭﻝ ﺩﻫﺔ ۱۹۰۰ می ﺗﻮﺍﻥ ﻳﺎﻓﺖ ﻭ ﺁﻥ ﺯﻣﺎﻧﻲ ﺍﺳﺖ ﻛﻪ Tyuring ﺩﺍﻧﺸﻤﻨﺪ ﺭوسی بر آن بود  ﻛﻪ ﺑﻪ ﺍﻓﺮﺍﺩ ﻣﺒﺘﻼ ﺑﻪ ﻧﺎﺭﺳﺎﻳﻴﻬﺎﻱ ﺑﻴﻨﺎﻳﻲ ﻛﻤﻚ ﻧﻤﺎﻳﺪ و ﺍﻭﻟﻴﻦ ﺍﺧﺘﺮﺍﻉ های ﺛﺒﺖ ﺷﺪﻩ ﺩﺭ ﺍﻳﻦ ﺯﻣﻴﻨﻪ مربوط به سالهای ۱۹۲۹ و ۱۹۳۳ هستند
ﺍﻳﻦ ﺳﻴﺴﺘﻢ ﻫﺎ ﺣﺮﻭﻑ ﭼﺎﭘﻲ ﺭﺍ ﺑﺎ ﺭﻭﺵ ﺗﻄﺎﺑﻖ ﻗﺎﻟﺒﻲ ﺷﻨﺎﺳﺎﻳﻲ ﻣﻲ كردند. ﻣﺎﺳﻜﻬﺎﻱ ﻣﻜﺎﻧﻴﻜﻲ ﻣﺨﺘﻠﻔﻲ ﺍﺯ ﻣﻘﺎﺑﻞ ﺗﺼﻮﻳﺮ ﺣﺮﻑ ﻋﺒﻮﺭ می ﻛﺮﺩﻧﺪ و نور از یك سو ﺑﻪ ﺁﻥ ﺗﺎﺑﺎﻧﺪﻩ ﺷﺪﻩ ﻭ ﺍﺯ ﺳﻮﻱ ﺩﻳﮕﺮ ﺗﻮﺳﻂ ﻳﻚ ﺁﺷﻜﺎﺭﺳﺎﺯ ﻧﻮﺭﻱ ﺩﺭﻳﺎﻓﺖ ﻣﻲ شد. وقتی یك انطباق كامل صورت می گرفت ﻧﻮﺭ ﺑﻪ ﺁﺷﻜﺎﺭﺳﺎﺯ ﻧﻤﻲ ﺭﺳﻴﺪ ﻭ ﺣﺮﻑ ﻭﺭﻭﺩﻱ ﺑﺎﺯﺷﻨﺎﺳﻲ ﻣﻲ شد. این ﺍﺧﺘﺮﺍﻉ ﺑﻪ ﺩﻟﻴﻞ ﺗﻜﻨﻮﻟﻮﮊﻱ ﺍﭘﺘﻮﻣﻜﺎﻧﻴﻜﻲ ﻣﻮﺭﺩ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﺁﻧﻬﺎ ﻛﺎﺭﺑﺮﺩﻱ ﻧﺒﻮﺩ و ﺗﺼﻮﺭ ﺩﺳﺘﺮﺳﻲ ﺑﻪ ﺩﺳﺘﮕﺎﻫﻲ ﺑﺮﺍﻱ ﺑﺎﺯﺷﻨﺎﺳﻲ ﺣﺮﻭﻑ ﺗﺎ ﺩﻫﻪ ۱۹۴۰ ﻣﻴﻼﺩﻱ ﻭ ﻇﻬﻮﺭ ﻛﺎﻣﭙﻴﻮﺗﺮﻫﺎﻱ ﺩﻳﺠﻴﺘﺎﻝ ﺑﺼﻮﺭﺕ ﻳﻚ ﺭﺅﻳﺎ ﺑﺎﻗﻲ ﻣﺎﻧﺪ.
ﺍﻗﺪﺍﻣﺎﺕ ﺍﻭﻟﻴﻪ ﺩﺭ ﺯﻣﻴﻨﺔ ﺑﺎﺯﺷﻨﺎﺳﻲ ﺣﺮﻭﻑ، ﺑﺮ ﺭﻭﻱ ﻣﺘﻮﻥ ﭼﺎﭘﻲ ﻭ ﻳﺎ ﻣﺠﻤﻮﻋﺔ ﻛﻮﭼﻜﻲ ﺍﺯ ﺣﺮﻭﻑ ﻭ ﻧﻤﺎﺩﻫﺎﻱ ﺩﺳﺘﻨﻮﻳﺲ ﻛﻪ ﺑﺮﺍﺣﺘﻲ ﻗﺎﺑﻞ ﺗﺸﺨﻴﺺ ﺑﻮﺩﻧﺪ، ﻣﺘﻤﺮﻛﺰ ﮔﺮﺩﻳﺪﻩ ﺑﻮﺩ. ﺳﻴﺴﺘﻤﻬﺎﻱ ﺑﺎﺯﺷﻨﺎﺳﻲ ﺣﺮﻭﻑ ﭼﺎﭘﻲ ﻛﻪ ﺩﺭ ﺍﻳﻦ ﻣﻘﻄﻊ ﺯﻣﺎﻧﻲ ﻣﻌﺮﻓﻲ ﺷﺪﻧﺪ، ﻋﻤﺪﺗﺎً ﺍﺯ ﺭﻭﺵ ﺗﻄﺎﺑﻖ ﻗﺎﻟﺒﻲ ﺍﺳﺘﻔﺎﺩﻩ می نمودند ﻛﻪ ﺩﺭ ﺁﻥ ﺗﺼﻮﻳﺮ ﻭﺭﻭﺩﻱ ﺑﺎ ﻛﺘﺎﺑﺨﺎﻧﻪ ای از تصاویر ﺣﺮﻭﻑ ﻣﻮﺭﺩ ﻣﻘﺎﻳﺴﻪ ﻗﺮﺍﺭ ﻣﻲ گرفت. در ﻣﻮﺭﺩ ﻣﺘﻮﻥ ﺩﺳﺘﻨﻮﻳﺲ ﻧﻴز ﺍﻟﮕﻮﺭﻳﺘﻤﻬﺎﻱ ﭘﺮﺩﺍﺯﺵ ﺗﺼﻮﻳﺮ ﻛﻪ ﻭﻳﮋﮔﻴﻬﺎﻱ ﺳﻄﺢ ﭘﺎﻳﻴﻦ را از تصاویر ﺍﺳﺘﺨﺮﺍﺝ ﻣﻲ كنند، ﺑﻪ ﺗﺼﺎﻭﻳﺮ ﺩﻭﺩﻭﻳﻲ ﺍﻋﻤﺎﻝ ﻣﻲ ﺷﺪ ﺗﺎ ﺑﺮﺩﺍﺭﻫﺎﻱ ﻭﻳﮋﮔﻲ ﺍﺳﺘﺨﺮﺍﺝ ﮔﺮﺩﻧﺪ. ﺳﭙﺲ ﺍﻳﻦ ﺑﺮﺩﺍﺭﻫﺎﻱ ﻭﻳﮋﮔﻲ ﺑﻪ ﻃﺒﻘﻪ ﻛﻨﻨﺪﻩ ﺁﻣﺎﺭﻱ ﺳﭙﺮﺩﻩ ﻣﻲ ﺷﺪﻧﺪ.
ﺩﺭ ﺍﻳﻦ ﺩﻭﺭﻩ، ﺗﺤﻘﻴﻘﺎﺕ ﻣﻮﻓﻖ ﺍﻣﺎ ﻣﻘﻴﺪﻱ ﺑﻴﺸﺘﺮ ﺑﺮ ﺭﻭﻱ ﺣﺮﻭﻑ ﻭ ﺍﻋﺪﺍﺩ لاتین ﺍﻧﺠﺎﻡ ﮔﺮﻓﺖ با ﺍﻳﻦ ﻭﺟﻮﺩ ﻣﻄﺎﻟﻌﺎﺕ ﭼﻨﺪﻱ ﻧﻴﺰ ﺩﺭ ﺯﻣﻴﻨﺔ ﺣﺮﻭﻑ ﮊﺍﭘﻨﻲ، ﭼﻴﻨﻲ، ﻋﺒﺮﻱ، ﻫﻨﺪﻱ، ﺳﻴﺮﻳﻠﻴﻜﻲ، ﻳﻮﻧﺎﻧﻲ ﻭ ﻋﺮﺑﻲ ﺩﺭ ﻫﺮ ﺩﻭ ﺯﻣﻴﻨﺔ ﺣﺮﻭﻑ ﭼﺎﭘﻲ ﻭ ﺩﺳﺘﻨﻮﻳﺲ ﺁﻏﺎﺯ ﮔﺮﺩﻳﺪ ﺑﺎ ﻇﻬﻮﺭ ﺻﻔﺤﺎﺕ ﺭﻗﻮﻣﻲ كننده ( ﺩﻳﺠﻴﺘﺎﻳﺰﺭﻫﺎ ) در دهه ۱۹۵۰ كه ﻗﺎﺩﺭ ﺑﻪ ﺗﺸﺨﻴﺺ ﻣﺨﺘﺼﺎﺕ ﺣﺮﻛﺘﻲ ﻧﻮﻙ ﻳﻚ ﻗﻠﻢ ﻣﺨﺼﻮﺹ ﺑﻮﺩﻧﺪ، ﺳﻴﺴﺘﻤﻬﺎﻱ OCR ﺗﺠﺎﺭﻱ ﻧﻴﺰ ﺍﻣﻜﺎﻥ ﻋﺮﺿﻪ ﻳﺎﻓﺘﻨﺪ. ﺍﻳﻦ ﻧﻮﺁﻭﺭﻱ ﺳﺒﺐ ﺷﺪ ﻛﻪ ﻣﺤﻘﻘﺎﻥ ﺑﺘﻮﺍﻧﻨﺪ ﺩﺭ ﺯﻣﻴﻨﺔ بازشناسایی حروف دست نویس فعالیت خود را آغاز نمایند.

ب ) ﻣﺮحله توسعه: (از سال ۱۹۸۰ تا ۱۹۹۰) 

ﻣﻄﺎﻟﻌﺎﺕ ﺻﻮﺭﺕ ﮔﺮﻓﺘﻪ ﺗﺎ ﻗﺒﻞ ﺍﺯ ﺳﺎﻝ ۱۹۸۰ ﺍﺯ ﻓﻘﺪﺍﻥ سخت افزارهای ﻛﺎﻣﭙﻴﻮﺗﺮﻱ ﻗﺪﺭﺗﻤﻨﺪ ﻭ ﺩﺳﺘﮕﺎﻫﻬﺎﻱ ﺍﺧﺬ ﺩﺍﺩﻩها رنج می بردند. در ﺍﻳﻦ ﺩﻫﻪ ﺑﻮﺍﺳﻄﺔ ﺭﺷﺪ ﺍﻧﻔﺠﺎﺭﮔﻮﻧﺔ ﺗﻜﻨﻮﻟﻮﮊﻱ اطلاعات، ﻭﺿﻌﻴﺖ ﺑﺴﻴﺎﺭ ﻣﻨﺎﺳﺒﻲ ﺑﺮﺍﻱ ﺯﻣﻴﻨﻪ ﻫﺎﻱ ﺗﺤﻘﻴﻘﺎﺗﻲ ﻣﺨﺘﻠﻒ ﺍﺯ ﺟﻤﻠﻪ ﺑﺎﺯﺷﻨﺎﺳﻲ ﺣﺮﻭﻑ ﻓﺮﺍﻫﻢ ﮔﺮﺩﻳﺪ. ﺭﻭﺷﻬﺎﻱ ﺳﺎﺧﺘﺎﺭﻱ ﺑﻪ ﻫﻤﺮﺍﻩ ﺭﻭﺷﻬﺎﻱ ﺁﻣﺎﺭﻱ ﺩﺭ ﺑﺴﻴﺎﺭﻱ ﺍﺯ ﺳﻴﺴﺘﻤﻬﺎ ﻇﺎﻫﺮ ﮔﺮﺩﻳﺪﻧﺪ.  ﺗﺤﻘﻴﻘﺎﺕ ﺩﺭ ﺯﻣﻴﻨﺔ OCR ﺍﺳﺎﺳﺎً ﺗﻮﺟﻪ ﺧﻮﺩ ﺭﺍ ﺑﻪ ﺭﻭﺷﻬﺎﻱ ﺑﺎﺯﺷﻨﺎﺳﻲ ﺍﺷﻜﺎﻝ ﺑﺪﻭﻥ ﺗﻮﺟﻪ ﺑﻪ ﻫﺮﮔﻮﻧﻪ اطلاعات ﻣﻌﻨﺎﺷﻨﺎﺧﺘﻲ ﻣﻌﻄﻮﻑ ﻧﻤﻮﺩ. این مسئله سبب ﮔﺮﺩﻳﺪ ﻛﻪ ﻧﺮﺥ ﺑﺎﺯﺷﻨﺎﺳﻲ نتواند ﺍﺯ ﻳﻚ ﺣﺪ ﺧﺎﺹ ﻓﺮﺍﺗﺮ بروﺩ. ﻛﻪ ﺩﺭ ﺑﺴﻴﺎﺭﻱ ﺍﺯ ﻛﺎﺭﺑﺮﺩﻫﺎﻱ OCR ﻗﺎﺑﻞ ﻗﺒﻮﻝ ﻧﺒﻮﺩ.

ج ) ﻣﺮحله بهبود: (از سال ۱۹۹۰ به بعد) 

ﺩﺭ ﺍﻳﻦ ﻣﻘﻄﻊ ﺯﻣﺎﻧﻲ ﺑﻮﺩ ﻛﻪ ﺑﺎ ﺗﻜﻮﻳﻦ ﺍﺑﺰﺍﺭﻫﺎ ﻭ ﺗﻜﻨﻴﻜﻬﺎﻱ ﭘﺮﺩﺍﺯﺷﻲ ﺟﺪﻳﺪ، ﭘﻴﺸﺮﻓﺖ ﻭﺍﻗﻌﻲ ﺳﻴﺴﺘﻤﻬﺎﻱ OCR ﻣﺤﻘﻖ ﮔﺮﺩﻳﺪ. ﺩﺭ ﺍﻭﺍﻳﻞ ﺩﻫﺔ ۱۹۹۰ ﺭﻭﺷﻬﺎﻱ ﭘﺮﺩﺍﺯﺵ ﺗﺼﻮﻳﺮ ﻭ ﺑﺎﺯﺷﻨﺎﺳﻲ ﺍﻟﮕﻮ ﺑﺎ ﺗﻜﻨﻴﻜﻬﺎﻱ ﻛﺎﺭﺁﻣﺪ ﻫﻮﺵ ﻣﺼﻨﻮﻋﻲ (AI) ﺍﺩﻏﺎﻡ ﮔﺸﺘﻨﺪ. ﻣﺤﻘﻘﺎﻥ ﺍﻟﮕﻮﺭﻳﺘﻤﻬﺎﻱ ﺑﺎﺯﺷﻨﺎﺳﻲ ﺣﺮﻭﻑ ﭘﻴﭽﻴﺪﻩ ﺭﺍ ﺍﺑﺪﺍع ﻧﻤﻮﺩﻧﺪ ﻛﻪ ﻗﺎﺩﺭ بودند ﺩﺍﺩﻩ ﻫﺎﻱ ﻭﺭﻭﺩﻱ ﺑﺎ ﺗﻔﻜﻴﻚ پذیری ﺑﺎﻻ ﺭﺍ ﺩﺭﻳﺎﻓﺖ ﻛﻨﻨﺪ ﻭ ﺩﺭ ﻣﺮﺣﻠﺔ ﭘﻴﺎﺩﻩ سازی، ﻣﺤﺎﺳﺒﺎﺕ ﺑﺴﻴﺎﺭ ﺯﻳﺎﺩﻱ ﺭﺍ ﺑﺮ ﺭﻭﻱ ﺩﺍﺩﻩ ﺍﻧﺠﺎﻡ ﺩﻫﻨﺪ. كه عبارتند از شبكه های عصبی ، منطق فازی و پردازش زبانهای طبیعی و غیره.

منبع

آشنایی با ماشین بینایی 

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

در حقیقت ماشین بینایی شاخه ای از علم مهندسی است که به رشته‌های علوم کامپیوتری (Computer science) و علم نورشناسی و مهندسی مکانیک و اتوماسیون صنعتی ارتباط دارد. یکی از مهمترین پر استفاده‌ترین کاربردهای آن در بازبینی و بررسی کالاهای صنعتی از جمله نیمه هادیها، اتومبیل ها، مواد خوراکی و دارو می باشد. همانند نیروی انسانی که با چشم غیر مسلح در خط تولید کالاها را برای تعیین کیفیت و نوع ساخت آنها بازبینی می کنند، ماشین بینایی از دوربین‌های دیجیتال و دوربین‌های هوشمند و نرم‌افزارهای image processing (پردازش تصویر) برای این کار استفاده می کند.

دستگاههای مربوطه (ماشین بینایی) برای انجام دادن وظایفی خاص از جمله شمردن اشیاء در بالابرها، خواندن شماره سریالها (Serial numbers)، جستجوی سطح‌های معیوب به کار می روند. در حال حاضر صنعت استفاده زیادی از سیستم ماشین بینایی برای بازبینی تصویری اشیاء (Visual inspection) که نیاز به سرعت بالا و دقت بالا و کار ۲۴ ساعته و تکرار محابات بالا دارد، وجود دارد.

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

علی رغم اینکه بعضی الگوریتم‌های ماشین بینایی برای تقلید کردن از سیستم بینایی انسان توسعه یافته اند، تعداد معدودی روش برای تحلیل و شناسایی ویژگیهای مرتبط تصاویر به صورت مؤثر و ثابت توسعه یافته اند. سیستم‌های Machine vision و computer vision قادر هستند به صورت ثابت تصاویر را تجزیه و تحلیل کنند، ولی image processing بر پایهٔ کامپیوتر به صورت کلی برای انجام کارهای تکراری طراحی می شوند و علی رغم پیشرفت‌های صورت گرفته در این زمینه، هیچ سیستم machine vision و computer vision قادر نیست با برخی از ویژگی‌های سیستم بینایی انسان در قالب درک تصویر، تلرانس به تغییرات نور، تضعیف قدرت تصویر و تغییرات اجزا و… تطبیق پیدا کند.

اجزای یک ماشین بینایی

اگرچه ماشین بینایی بیشتر به عنوان یک پروسهٔ به کار بستنٍ “Machine vision” در کاربردهای صنعتی شناخته شده است، برای لیست کردن اجزای سخت‌افزاری و نرم‌افزاری به کار برده شده نیز مفید می باشد. معمولاً یک ماشین بینایی از اجزای زیر ساخته میشود :

۱٫ یک و یا چند دوربین دیجیتال یا آنالوگ ( سیاه-سفید یا رنگی ) با اپتیک مناسب برای گرفتن عکس.
۲٫ واسطه ای که عکس‌ها را برای پردازش آماده می سازد. برای دوربین‌های آنالوگ این واسطه شامل یک دیجیتال کننده عکس است. هنگامی که این واسطه یک سخت‌افزارٍ جدا باشد، به آن Frame grabber ( کارتی که برای دریافت سیگنال تصویری و فرستادن آن به کامپیوتر استفاده می شود)می گویند.
۳٫ یک پردازشگر ( گاهی یک PC یا پردازنده تعبیه شده ( Embedded Processor ) مانند DSP
۴٫ نرم‌افزار ماشین بینایی : این نرم‌افزار امکاناتی برای توسعه یک برنامه نرم‌افزاری که برای کاربردی مشخص است را فراهم می کند.
۵٫ سخت‌افزار ورودی / خروجی ( مثلا I/O دیجیتال ) یا حلقه‌های ارتباطی ( مثلا ارتباط شبکه ای یا RS-232 ) برای گزارش نتایج.
۶٫ یک دوربین هوشمند : یک وسیله ساده که همه موارد فوق را داراست.
۷٫ لنزهایی که بتواند به مقدار مطلوبی روی سنسور تصویر زوم کند.
۸٫ منابع نوری مناسب و گاهی خیلی مخصوص ( مثلا چراغهای LED، فلورسنت، لامپهای هالوژن و . . . )
۹٫ یک برنامهٔ مشخص که بتواند تصاویر را پردازش کرده و مشخصه‌های مربوط و مناسب را شناسایی کند.
۱۰٫ یک سنسور همزمان ساز برای شناسایی اجزا ( گاهی یک سنسور نوری و یا یک سنسور مغناطیسی ) : این سنسور برای راه اندازی سیستمٍ استخراج و پردازش تصویر می باشد.

سنسور همزمان ساز تعیین می‌کند که چه زمانی یک بخش ( که معمولاً روی یک حمل کننده حرکت می کند) در موقعیتی قرار گرفته است که باید مورد بررسی واقع شود. این سنسور هنگامیکه از زیر دوربین می گذرد و یک پالس نوری برای ثابت نگهداشتن تصویر ایجاد می‌کند، دوربین را برای گرفتن عکس فعال می کند. نوری که برای روشن کردن آن بخش به کار می رود در واقع برای آن است که مشخصه‌های مطلوب را برجسته و مشخصات نامطلوب ( مثل سایه‌ها و یا انعکاس ها) را به حداقل برساند. معمولاً پنل‌های LED با اندازه و طراحی مناسب برای این هدف مورد استفاده قرار می گیرند. تصویر دوربین یا توسط یک frame grabber و یا توسط یک حافظه کامپیوتری (که در آن از frame grabber استفاده نشده است) گرفته می شود.

frame grabber یک وسیله دیجیتال کننده است ( یا در داخل دوربین هوشمند و یا بطور جداگانه) که خروجی دوربین را به فرمت دیجیتال تبدیل کرده ( معمولاً این فرمت از یک آرایه دو بعدی از اعداد تشکیل شده که هر عدد متناظر شدت روشنایی نقطه متناظر در آن تصویر می باشد. به این نقاط پیکسل می گویند.) و سپس تصویر را به منظور پردازش توسط نرم‌افزارٍ ماشین بینایی در حافظه کامپیوتر ذخیره می کند. به طور معمول نرم‌افزار، اقدامات متفاوتی را برای پردازش تصویر انجام می دهد. گاهی در ابتدا تصویر برای کاهش نویز و یا تبدیل سایه‌های خاکستری به ترکیب ساده ای از رنگهای سیاه و سفید دستکاری می‌شود ( Binarization ).

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

همچنین امروزه شاهد شیوع فراوان استفاده از تجهیزات دوربین‌های دیجیتال به جای یک دوربین و یک frame grabber جداگانه در ماشین بینایی هستیم. استفاده از یک دوربین دیجیتال به منظور برقراری ارتباط مستقیم، باعث صرفه جویی در هزینه و نیز سادگی سیستم خواهد شد. دوربین‌های هوشمند که در داخل آنها embedded processor‌ها تعبیه شده اند، در حال تسخیر سهم بالایی از بازار ماشین بینایی ها هستند. استفاده از یک embedded processor ( و یا یک پردازنده بهینه ) نیاز ما به frame grabber و یک کامپیوتر خارجی را از بین می برد. به همین خاطر این پردازنده‌ها باعث کاهش هزینه، کاهش پیچیدگی سیستم و همچنین اختصاص توان پردازشی مشخص به هر دوربین می شود. دوربین‌های هوشمند معمولاً ارزان تر از سیستمهای شامل یک دوربین و یک برد و یک کامپیوتر خارجی هستند. همچنین توان بالای embedded processor و DSP‌ها منجر به بالا رفتن عملکرد و توانایی آنها نسبت به سیستمهای مرسوم ( که بر مبنای PC هستند ) شده است.
منبع

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

همایش جامع بین المللی کامپیوتر، فناوری اطلاعات ومهندسی برق در تاریخ ۱۹ اسفند ۱۳۹۶ توسط و تحت حمایت سیویلیکا برگزار می شود.با توجه به اینکه این همایش به صورت رسمی برگزار می گردد، کلیه مقالات این کنفرانس در پایگاه سیویلیکا و نیز کنسرسیوم محتوای ملی نمایه خواهد شد و شما می توانید با اطمینان کامل، مقالات خود را در این همایش ارائه نموده و از امتیازات علمی ارائه مقاله کنفرانس با دریافت گواهی کنفرانس استفاده کنید.

 

حوزه های تحت پوشش: علوم کامپیوتر
برگزار کننده:
سایر برگزار کنندگان: تحت حمایت سیویلیکا

محورهای همایش:
علوم کامپیوتر
مهندسی نرم افزار
سیستم های نرم افزای

مهندسی نرم افزار و سیستم های صوری
معماری نرم افزار
تست و ارزیابی سیستم های نرم افزاری،
نظریه محاسبات
رایانش ابری
داده های عظیم و سایر موارد مرتبط

پایگاه داده عملیاتی و تحلیلی
داده کاوی
امنیت اطلاعات و امنیت سیستم های نرم افزاری
سایر مباحث مرتبط با مهندسی نرم افزار و محاسبات مشبک و خوشه ای
مباحث ویژه در مهندسی نرم افزار

هوش مصنوعی
هوش مصنوعی و یادگیری
بینایی ماشین و پردازش تصویر

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

سیستم های استنتاج
شناسایی الگو
سیستم چند عامله
یادگیری ماشین
بینایی ماشین و پردازش تصویر
پردازش تکاملی
مباحث ویژه در سیستم هوشمند و محاسبات نرم
سایر مباحث مرتبط با سیستم های هوشمند و سایر موارد

شبکه های کامپیوتری
انتقال داده
امنیت شبکه های کامپیوتری
شبکه های هوشمند برق
شبکه های بین خودرویی
شبکه های اقتضای
شبکه های ارتباطی موبابل
شبکه های بی سیم و سایر موارد مرتبط

معماری کامپیوتر
سیستم های حسابی
قابلیت اطمینان
تحمل پذیری خطا و آزمون پذیری
معماری سیستم های موازی
مدل سازی و ارزیابی کارایی سیستم های کامپیوتری

سیستم های نهفته و بی درنگ
سیستم های قابل پیکربندی
شبکه های ارتباطی موبایل و بی سیم
مدارای مجتمع در سیستم های بسیار بزرگ
فناوری نوظهور
مباحث ویژه در سیستم دیجیتالی
سیستم های سلولی
سیستم توزیع شده
سایر مباحث مرتبط با سیستم های دیجیتالی و سایر موارد مرتبط

فناوری اطلاعات و ارتباطات
شبکه های کامپیوتری
انتقال داده
امنیت شبکه های کامپیوتری
محسبات خوشه ای، مشبک و ابری
یادگیری الکترونیک

معماری اطلاعات و مدیریت دانش
پردازش موازی و سیستم های توزیع شده
معماری سازمانی فناوری اطلاعات
سیستم های محاسباتی انسان محور
تجارت الکترونیک
مدل سازی و ارزیابی شبکه های کامپیوتری
سیستم های انتقال و ارتباطات هوشمند
مباحث ویژه در شبکه های کامپیوتری
سایر :

الگوریتم و محاسبات
بیوانفورماتیک و محاسبات علمی
تجارت الکترونیک، دولت الکترونیک
آموزش از راه دور (آموزش الکترونیکی(
موتورهای گرافیکی، موتورهای بازی و انیمیشن
سیستم های چندرسانه ای، گرافیک و شبیه سازی

برق :
قدرت
کنترل
مخابرات
الکترونیک
مکاترونیک
مخابرات نوری
مهندسی پزشکی
تکنولوژی فشار قوی

پزشکی(بیوالکتریک)
ماشین های الکتریکی
هوش ماشین و رباتیک
کنترل و ابزار دقیق و اتوماسیون (ACI)
شیمی و مواد (CAM)
کنترل و حفاظت (CAP)
دیسپاچینگ و مخابرات (DTC)
بهره‌وری و مدیریت انرژی (EEM)

ماشین‌های الکتریکی (ELM)
محیط زیست، ایمنی و بهداشت (ENV)
تولید انرژی الکتریکی (EPG)
بازار برق (EPM)
پست‌های فشارقوی (HVS)
تکنولوژی اطلاعات (ITP)
مدیریت (MNG)

توزیع انرژی الکتریکی (PDS)
کیفیت برق (PQA)
برنامه‌ریزی و مطالعات سیستم (PSS)
انتقال انرژی الکتریکی (PTL)
انرژی‌های تجدیدپذیر (REN)
مطالعات اقتصادی و اجتماعی (SEA)
شبکه‌های هوشمند (SMG)
ترانسفورماتورهای قدرت و توزیع (TRN)