آموزش پردازش تصویر با سی شارپ به صورت عملی
پردازش تصویر یا Image Processing یکی از حوزههای نوظهور و تاثیرگذار در دنیای امروز است که با استفاده از آن میتوانیم عملیات مختلفی را بر روی تصاویر انجام داده و دادههای مهم را از آن استخراج کنیم. برای مثال با استفاده از پردازش تصویر و بینایی ماشین میتوان ویدیوهایی دریافتی از دوربینهای پلاک خوان را تجزیه کرده و پلاک خودروها را تشخیص داد. برای پردازش دادههای مربوط به ویدیوها و تصاویر دریافتی، زبانهای برنامههای مختلفی وجود دارد که یکی از بهترین آنها C# است. سی شارپ این امکان را میدهد تا عملیات مختلفی مثل افزایش وضوح، اعمال فیلترهای رنگی و زوم کردن را بر روی تصاویر انجام دهیم. در این نوشته قصد داریم آموزش پردازش تصویر با سی شارپ را با شما عزیزان به اشتراک بگذاریم تا اطلاعات بیشتری در این خصوص داشته باشید.
پردازش تصویر با سی شارپ
زبان برنامه نویسی C# بسیار قدرتمند بوده و با استفاده از آن میتوان صفر تا صد پروژه پردازش تصویر را انجام داد. همچنین امکان استفاده از کتابخانههایی مثل OpenCV و OpenGL نیز وجود دارد. با استفاده از این کتابخانهها میتوانید بسیاری از کارها را در مدت زمان کوتاه و با کمترین کدنویسی انجام دهید.
در حالت کلی Image Processing به مجموعهای از پردازشها و عملیات گفته میشود که هدف آنها بهبود کیفیت تصاویر، دستکاری آنها یا استخراج اطلاعات از دادههای تصویری است. پردازش تصویر یکی از گامهای مهم در پردازش دادههای تصویر است تا از خروجی آنها در پروژههای تشخیص چهره، تشخیص پلاک خودرو و تشخیص بیماریها استفاده شود.
آموزش image processing در سی شارپ
در آموزش پردازش تصویر با سی شارپ قصد داریم یک برنامه ایجاد کنیم که تصویر را دریافت کرده و عملیات مختلفی از جمله زوم کردن، فیلتر رنگ، تغییر کنتراست، تغییر روشنایی، سیاه و سفید کردن، معکوس کردن، تغییر اندازه و درج متن را بر روی تصاویر اعمال کند. برای ساخت این برنامه از Windows Forms استفاده کرده و برای مدیریت عملیات یک کلاس به نام ImageHandler ایجاد میکنیم.
پیشنهاد مطالعه: آموزش Generic در سی شارپ به زبان ساده + مثال عملی
۱. اعمال فیلترهای رنگی بر روی تصاویر
اولین بخش از آموزش پردازش تصویر با سی شارپ به اعمال فیلترهای رنگی اختصاص دارد. تصاویر رنگی از سه کانال اصلی قرمز، سبز و آبی ساخته شدهاند و برای نامگذاری آنها از حروف انگلیسی R (Red)، G (Green) و B (Blue) استفاده میکنند. هر کدام از این کانالها مقداری در بازه 0 تا 255 میگیرند. در صورتی که هر سه این کانالها دارای مقدار 0 باشند (0, 0 ,0)، رنگ تصویر مشکی و اگر عدد کانالها برابر با 255 باشد، رنگ تصویر سفید خواهد شد.
حال برای اینکه فیلترهای رنگی مختلف را در سی شارپ بر روی تصاویر اعمال کنیم، کافی است یکی از رنگها را بر روی 255 یا اعداد پایین نگه داشته و دو رنگ بعدی را کم کنیم. برای مثال برای اعمال فیلتر قرمز بر روی تصویر، رنگهای آبی و سبز را از تصویر کم کرده و فقط رنگ قرمز را نگه میداریم. در کد زیر میتوانید مراحل انجام آن را در سی شارپ مشاهده نمایید.
public void SetColorFilter(ColorFilterTypes colorFilterType) { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)temp.Clone(); Color c; for (int i = 0; i < bmap.Width; i++) { for (int j = 0; j < bmap.Height; j++) { c = bmap.GetPixel(i, j); int nPixelR = 0; int nPixelG = 0; int nPixelB = 0; if (colorFilterType == ColorFilterTypes.Red) { nPixelR = c.R; nPixelG = c.G - 255; nPixelB = c.B - 255; } else if (colorFilterType == ColorFilterTypes.Green) { nPixelR = c.R - 255; nPixelG = c.G; nPixelB = c.B - 255; } else if (colorFilterType == ColorFilterTypes.Blue) { nPixelR = c.R - 255; nPixelG = c.G - 255; nPixelB = c.B; } nPixelR = Math.Max(nPixelR, 0); nPixelR = Math.Min(255, nPixelR); nPixelG = Math.Max(nPixelG, 0); nPixelG = Math.Min(255, nPixelG); nPixelB = Math.Max(nPixelB, 0); nPixelB = Math.Min(255, nPixelB); bmap.SetPixel(i, j, Color.FromArgb((byte)nPixelR, (byte)nPixelG, (byte)nPixelB)); } } _currentBitmap = (Bitmap)bmap.Clone(); }
۲. تغییر مقدار گاما (Gamma)
یکی دیگر از کارهایی که میتوانید در Image Processing بر روی تصاویر انجام دهید، تغییر مقدار گاما است. Gamma یک پارامتر در رنگهای تصاویر است که برای تصحیح روشنایی تصاویر و ویدیوها مورد استفاده قرار میگیرد.
در صورتی که میخواهید تصاویر به صورت دقیق در مانیتور نمایش داده شود، تغییر دادههای مربوط به گاما اهمیت زیادی دارد.
تصاویری که میزان گاما در آنها به درستی تصحیح نشده است، احتمال دارد خیلی سفید یا خیلی سیاه باشند. بهتر است بدانید تغییر مقدار گاما علاوه بر روشنایی، باعث تغییر نسبت سایر رنگها به یکدیگر میشود. رنج عددی که میتوانید برای Gamma در نظر بگیرید بین 0.2 الی 5 است.
public void SetGamma(double red, double green, double blue) { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)temp.Clone(); Color c; byte[] redGamma = CreateGammaArray(red); byte[] greenGamma = CreateGammaArray(green); byte[] blueGamma = CreateGammaArray(blue); for (int i = 0; i < bmap.Width; i++) { for (int j = 0; j < bmap.Height; j++) { c = bmap.GetPixel(i, j); bmap.SetPixel(i, j, Color.FromArgb(redGamma[c.R], greenGamma[c.G], blueGamma[c.B])); } } _currentBitmap = (Bitmap)bmap.Clone(); }
برای ایجاد آرایه گاما نیز میتوانید از کد زیر استفاده کنید.
private byte[] CreateGammaArray(double color) { byte[] gammaArray = new byte[256]; for (int i = 0; i < 256; ++i) { gammaArray[i] = (byte)Math.Min(255, (int)((255.0 * Math.Pow(i / 255.0, 1.0 / color)) + 0.5)); } return gammaArray; }
۳. آموزش پردازش تصویر با سی شارپ برای تغییر روشنایی تصاویر
پایین بودن میزان روشنایی یا Brightness در تصاویر باعث تیرگی و کاهش کیفیت میشود. در پروژه پردازش تصاویر مقدار Brightness عددی بین -255 تا 255 است. برای تغییر میزان روشنایی در تصاویر میتوانید از کد زیر استفاده کنید.
public void SetBrightness(int brightness) { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)temp.Clone(); if (brightness < -255) brightness = -255; if (brightness > 255) brightness = 255; Color c; for (int i = 0; i < bmap.Width; i++) { for (int j = 0; j < bmap.Height; j++) { c = bmap.GetPixel(i, j); int cR = c.R + brightness; int cG = c.G + brightness; int cB = c.B + brightness; if (cR < 0) cR = 1; if (cR > 255) cR = 255; if (cG < 0) cG = 1; if (cG > 255) cG = 255; if (cB < 0) cB = 1; if (cB > 255) cB = 255; bmap.SetPixel(i, j, Color.FromArgb((byte)cR, (byte)cG, (byte)cB)); } } _currentBitmap = (Bitmap)bmap.Clone(); }
۴. تغییر کنتراست تصاویر (Contrast)
یکی دیگر از مواردی که در آموزش پردازش تصاویر با سی شارپ مطرح خواهیم کرد، نحوه تغییر کنتراست تصویر است. کنتراست یا تضاد به اختلاف بین روشنترین و تاریکترین بخشهای تصویر گفته میشود. هر چقدر این اختلاف بیشتر باشد، کنتراست نیز بیشتر خواهد شد. دقت داشته باشید که با افزایش کنتراست، کیفیت تصویر نیز بهبود پیدا میکند و اجزای آن به راحتی قابل تشخیص هستند.
در سی شارپ میتوانید کنتراست را عددی بین -100 تا 100 انتخاب کنید؛ اما توصیه میکنیم آن را بین 0 تا 4 نگه دارید.
public void SetContrast(double contrast) { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)temp.Clone(); if (contrast < -100) contrast = -100; if (contrast > 100) contrast = 100; contrast = (100.0 + contrast) / 100.0; contrast *= contrast; Color c; for (int i = 0; i < bmap.Width; i++) { for (int j = 0; j < bmap.Height; j++) { c = bmap.GetPixel(i, j); double pR = c.R / 255.0; pR -= 0.5; pR *= contrast; pR += 0.5; pR *= 255; if (pR < 0) pR = 0; if (pR > 255) pR = 255; double pG = c.G / 255.0; pG -= 0.5; pG *= contrast; pG += 0.5; pG *= 255; if (pG < 0) pG = 0; if (pG > 255) pG = 255; double pB = c.B / 255.0; pB -= 0.5; pB *= contrast; pB += 0.5; pB *= 255; if (pB < 0) pB = 0; if (pB > 255) pB = 255; bmap.SetPixel(i, j, Color.FromArgb((byte)pR, (byte)pG, (byte)pB)); } } _currentBitmap = (Bitmap)bmap.Clone(); }
۵. آموزش پردازش تصویر با سی شارپ برای سیاه و سفید کردن تصاویر
فیلتر دیگری که امکان اعمال آن بر روی تصاویر وجود دارد، فیلتر خاکستری است. در این حالت رنگهای تصویر به رنگهای سیاه و سفید تبدیل میشوند.
public void SetGrayscale() { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)temp.Clone(); Color c; for (int i = 0; i < bmap.Width; i++) { for (int j = 0; j < bmap.Height; j++) { c = bmap.GetPixel(i, j); byte gray = (byte)(.299 * c.R + .587 * c.G + .114 * c.B); bmap.SetPixel(i, j, Color.FromArgb(gray, gray, gray)); } } _currentBitmap = (Bitmap)bmap.Clone(); }
۶. اعمال فیلتر معکوس بر روی تصاویر (Invert)
یکی دیگر از مواردی که در آموزش پردازش تصویر با سی شارپ میتوانید انجام دهید، معکوس کردن رنگ تصاویر است. برای مثال اگر رنگ یک پیکسل از تصویر 00 باشد، آن را تبدیل به FF خواهد کرد.
با اعمال این فیلتر، تصاویر حالت نگاتیوی پیدا میکنند.
public void SetInvert() { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)temp.Clone(); Color c; for (int i = 0; i < bmap.Width; i++) { for (int j = 0; j < bmap.Height; j++) { c = bmap.GetPixel(i, j); bmap.SetPixel(i, j, Color.FromArgb(255 - c.R, 255 - c.G, 255 - c.B)); } } _currentBitmap = (Bitmap)bmap.Clone(); }
۷. تغییر سایز تصاویر (Resize)
در تغییر سایز تصاویر فقط اندازه عرض و ارتفاع تغییر پیدا میکند و تاثیری بر روی پیکسلها ندارد؛ بنابراین وضوح تصویر به همان حالت خود باقی میماند.
public void Resize(int newWidth, int newHeight) { if (newWidth != 0 && newHeight != 0) { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = new Bitmap(newWidth, newHeight, temp.PixelFormat); double nWidthFactor = (double)temp.Width / (double)newWidth; double nHeightFactor = (double)temp.Height / (double)newHeight; double fx, fy, nx, ny; int cx, cy, fr_x, fr_y; Color color1 = new Color(); Color color2 = new Color(); Color color3 = new Color(); Color color4 = new Color(); byte nRed, nGreen, nBlue; byte bp1, bp2; for (int x = 0; x < bmap.Width; ++x) { for (int y = 0; y < bmap.Height; ++y) { fr_x = (int)Math.Floor(x * nWidthFactor); fr_y = (int)Math.Floor(y * nHeightFactor); cx = fr_x + 1; if (cx >= temp.Width) cx = fr_x; cy = fr_y + 1; if (cy >= temp.Height) cy = fr_y; fx = x * nWidthFactor - fr_x; fy = y * nHeightFactor - fr_y; nx = 1.0 - fx; ny = 1.0 - fy; color1 = temp.GetPixel(fr_x, fr_y); color2 = temp.GetPixel(cx, fr_y); color3 = temp.GetPixel(fr_x, cy); color4 = temp.GetPixel(cx, cy); // Blue bp1 = (byte)(nx * color1.B + fx * color2.B); bp2 = (byte)(nx * color3.B + fx * color4.B); nBlue = (byte)(ny * (double)(bp1) + fy * (double)(bp2)); // Green bp1 = (byte)(nx * color1.G + fx * color2.G); bp2 = (byte)(nx * color3.G + fx * color4.G); nGreen = (byte)(ny * (double)(bp1) + fy * (double)(bp2)); // Red bp1 = (byte)(nx * color1.R + fx * color2.R); bp2 = (byte)(nx * color3.R + fx * color4.R); nRed = (byte)(ny * (double)(bp1) + fy * (double)(bp2)); bmap.SetPixel(x, y, System.Drawing.Color.FromArgb (255, nRed, nGreen, nBlue)); } } _currentBitmap = (Bitmap)bmap.Clone(); } }
پیشنهاد مطالعه: آموزش HttpClient در سی شارپ به همراه مثالهای واقعی
۸. چرخش تصویر (Rotating and Flipping)
زمانی که این فیلتر بر روی تصویر اعمال میشود، حالت آینهای پیدا میکند. این کار به سادگی و با فراخوانی enum انجام میشود.
public void RotateFlip(RotateFlipType rotateFlipType) { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)temp.Clone(); bmap.RotateFlip(rotateFlipType); _currentBitmap = (Bitmap)bmap.Clone(); }
۹. برش تصاویر (Crop)
مساله بعدی که در آموزش پردازش تصویر با سی شارپ به آن خواهیم پرداخت، برش تصاویر یا کراپ است. برش تصاویر را در دو مرحله انجام میدهیم؛ ابتدا قسمتهای غیرضروری را به صورت نیمه شفاف در میآوریم. سپس این قسمتها را حذف میکنیم تا ناحیه انتخابی برش داده شود.
public void DrawOutCropArea(int xPosition, int yPosition, int width, int height) { _bitmapPrevCropArea = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)_bitmapPrevCropArea.Clone(); Graphics gr = Graphics.FromImage(bmap); Brush cBrush = new Pen(Color.FromArgb(150, Color.White)).Brush; Rectangle rect1 = new Rectangle(0, 0, _currentBitmap.Width, yPosition); Rectangle rect2 = new Rectangle(0, yPosition, xPosition, height); Rectangle rect3 = new Rectangle (0, (yPosition + height), _currentBitmap.Width, _currentBitmap.Height); Rectangle rect4 = new Rectangle((xPosition + width), yPosition, (_currentBitmap.Width - xPosition - width), height); gr.FillRectangle(cBrush, rect1); gr.FillRectangle(cBrush, rect2); gr.FillRectangle(cBrush, rect3); gr.FillRectangle(cBrush, rect4); _currentBitmap = (Bitmap)bmap.Clone(); }
بعد از اینکه کاربر ناحیه مورد نظر را انتخاب کرد، یک پیغام نمایش داده میشود تا از برش تصویر اطمینان حاصل کنیم.
اگر کاربر OK را انتخاب کند، تصویر برش داده میشود.
public void Crop(int xPosition, int yPosition, int width, int height) { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)temp.Clone(); if (xPosition + width > _currentBitmap.Width) width = _currentBitmap.Width - xPosition; if (yPosition + height > _currentBitmap.Height) height = _currentBitmap.Height - yPosition; Rectangle rect = new Rectangle(xPosition, yPosition, width, height); _currentBitmap = (Bitmap)bmap.Clone(rect, bmap.PixelFormat); }
۱۰. اضافه کردن متن و اشکال به تصاویر
یکی دیگر از کارهایی که در پردازش تصاویر میتوانید انجام دهید، اضافه کردن اشکال گرافیکی و متن به تصویر است. برای انجام همه این کارها از متد Graphics استفاده میکنیم.
کد مربوط به اضافه کردن متن به تصویر
public void InsertText(string text, int xPosition, int yPosition, string fontName, float fontSize, string fontStyle, string colorName1, string colorName2) { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)temp.Clone(); Graphics gr = Graphics.FromImage(bmap); if (string.IsNullOrEmpty(fontName)) fontName = "Times New Roman"; if (fontSize.Equals(null)) fontSize = 10.0F; Font font = new Font(fontName, fontSize); if (!string.IsNullOrEmpty(fontStyle)) { FontStyle fStyle = FontStyle.Regular; switch (fontStyle.ToLower()) { case "bold": fStyle = FontStyle.Bold; break; case "italic": fStyle = FontStyle.Italic; break; case "underline": fStyle = FontStyle.Underline; break; case "strikeout": fStyle = FontStyle.Strikeout; break; } font = new Font(fontName, fontSize, fStyle); } if (string.IsNullOrEmpty(colorName1)) colorName1 = "Black"; if (string.IsNullOrEmpty(colorName2)) colorName2 = colorName1; Color color1 = Color.FromName(colorName1); Color color2 = Color.FromName(colorName2); int gW = (int)(text.Length * fontSize); gW = gW == 0 ? 10 : gW; LinearGradientBrush LGBrush = new LinearGradientBrush(new Rectangle(0, 0, gW, (int)fontSize), color1, color2, LinearGradientMode.Vertical); gr.DrawString(text, font, LGBrush, xPosition, yPosition); _currentBitmap = (Bitmap)bmap.Clone(); }
کد اضافه کردن یک تصویر به تصویر اصلی
public void InsertImage(string imagePath, int xPosition, int yPosition) { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)temp.Clone(); Graphics gr = Graphics.FromImage(bmap); if (!string.IsNullOrEmpty(imagePath)) { Rectangle rect = new Rectangle(xPosition, yPosition, i_bitmap.Width, i_bitmap.Height); gr.DrawImage(Bitmap.FromFile(imagePath), rect); } _currentBitmap = (Bitmap)bmap.Clone(); }
کد اضافه کردن اشکال گرافیکی به عکس
public void InsertShape(string shapeType, int xPosition, int yPosition, int width, int height, string colorName) { Bitmap temp = (Bitmap)_currentBitmap; Bitmap bmap = (Bitmap)temp.Clone(); Graphics gr = Graphics.FromImage(bmap); if (string.IsNullOrEmpty(colorName)) colorName = "Black"; Pen pen = new Pen(Color.FromName(colorName)); switch (shapeType.ToLower()) { case "filledellipse": gr.FillEllipse(pen.Brush, xPosition, yPosition, width, height); break; case "filledrectangle": gr.FillRectangle(pen.Brush, xPosition, yPosition, width, height); break; case "ellipse": gr.DrawEllipse(pen, xPosition, yPosition, width, height); break; case "rectangle": default: gr.DrawRectangle(pen, xPosition, yPosition, width, height); break; } _currentBitmap = (Bitmap)bmap.Clone(); }
شما میتوانید برنامهای شبیه به تصویر زیر ایجاد کرده و با قرار دادن دکمههای مختلف، هر کدام از تغییرات بالا را بر روی تصاویر اعمال کنید.
آشنایی با کتابخانه OpenCV برای پردازش تصویر در سی شارپ
کتابخانه OpenCV بیش از 2 هزار الگوریتم در اختیار برنامهنویسان قرار میدهد تا مسائل مربوط به پردازش تصویر و بینایی ماشین را انجام دهند. این کتابخانه در اکثر زبانهای برنامه نویسی از جمله C# در دسترس است. با OpenCV عملیات مختلفی را میتوان بر روی تصاویر انجام داد که برخی از آنها عبارتند از:
- برش و تقطیع تصاویر
- اعمال فیلترهای رنگی مختل
- انجام پردازش بر روی ساختار تصاویر
- بهبود کیفیت تصاویر
- تبدیل فضای رنگی تصاویر
پردازش تصاویر با سی شارپ را حرفهای یاد بگیرد!
پردازش تصویر یک مبحث بسیار پیشرفته در رشته علوم کامپیوتر است. امروزه از این قابلیت برای بازسازی تصاویر، استخراج اطلاعات و اعمال تغییرات بر روی تصاویر استفاده میشود. پردازش تصاویر کاربردهای بسیار گستردهای دارد که از جمله آنها میتوان به بازشناسی الگو و شناسایی اشیا در تصاویر، ساخت حسگرهای راه دور، بازسازی عکسهای دیجیتال، پردازش تصاویر دوربینهای کنترل ترافیک و بازیابی تصاویر پزشکی اشاره کرد.
در آموزش پردازش تصویر با سی شارپ سعی کردیم نکات ابتدایی و مهم در رابطه با این مساله را با شما عزیزان به اشتراک بگذاریم. اگر قصد دارید با الگوریتمهای image Processing به طور جامع و کاربردی آشنا شوید، توصیه میکنیم در دورههای آموزش پردازش تصویر و آموزش سی شارپ مکتب خونه شرکت کنید. اساتید این دورهها همه مباحث را از مبتدی تا پیشرفته و به سادهترین شکل ممکن در اختیار دانشجویان قرار میدهند. بعد از اتمام دورهها و دریافت مدرک میتوانید وارد بازار کار شده و به کسب درآمد بپردازید. سورس پردازش تصاویر با C# نیز در اختیار دانشجویان قرار داده میشود تا مطالب را به صورت جامع و کامل یاد بگیرند.