株式会社MITECH
Machine
Imagination Technologies
エム・アイ・テク

 

Useful OpenCVsharp Sample Codes

 

yêu cầu ============
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI;
using static System.Net.Mime.MediaTypeNames;
using System.Web.UI.WebControls;
using Point = System.Drawing.Point;
using OpenCvSharp.Extensions;
============

access pixel ảnh bitmap

============
void access_to_pixel_bitmap()
{
   // 1. Đọc dữ liệu từ ổ cứng (disk) và xử lý ngoại lệ nếu có lỗi
   Bitmap imageBmp         = new Bitmap("put/your/image/path/here");
   BitmapData imageBmpData = imageBmp.LockBits(new Rectangle(), ImageLockMode.ReadOnly, imageBmp.PixelFormat);

   // 2. Truy cập đến từng pixel dùng vòng lặp
   unsafe
   {
      // 2.1 Lấy địa chỉ trực tiếp của con trỏ đến ảnh
      byte* ptr         = (byte*)imageBmpData.Scan0;
      int bytesPerPixel = System.Drawing.Image.GetPixelFormatSize(imageBmp.PixelFormat) / 8;
      int dataStride    = imageBmpData.Stride;
      int imageWidth    = imageBmpData.Width;
      int imageHeight   = imageBmpData.Height;

      // 2.2 Duyệt qua từng pixel của từng kênh màu
      for (int y = 0; y < imageHeight; y++)
      {
         int offsetX = y * dataStride;
         for (int x = 0; x < imageWidth; x++)
         {
            // 1.Compute the pixel's offset
            int offsetY = offsetX + (x * bytesPerPixel);

            // 2. Lấy dữ liệu của từng kênh màu
            byte tmpBlue  = ptr[offsetY];
            byte tmpGreen = ptr[offsetY + 1];
            byte tmpRed   = ptr[offsetY + 2];

            // Xử lý logic với dữ liệu vừa lấy được
            // Dưới đây chỉ là phần ví dụ về xử lý logic
            {
               // Todo: Xử lý logic ở đây
               ptr[offsetY]     = (byte)(255 - tmpBlue);
               ptr[offsetY + 1] = (byte)(255 - tmpGreen);
               ptr[offsetY + 2] = (byte)(255 - tmpRed);
            }
         }
      }
   }

   // 3. Release resource khi không dùng nữa
   if(imageBmp != null)
   {
      if(imageBmpData!= null )
         imageBmp.UnlockBits(imageBmpData);

      // Nếu không dùng đến ảnh bitmap thì dispose ở đây luôn
      imageBmp.Dispose();
   }
}
============

vẽ text lên ảnh ============
void draw_text_on_bitmap(
   ref Bitmap image,                // inout : Ảnh input cũng là output
   string textContent,              // input : Nội dung cần vẽ lên ảnh
   Point textPosition,              // input : Vị trí cần vẽ text
   Color textColor,                 // input : Màu text
   string fontName = "Consolas",    // input : Font vẽ lên text, mặc định là consolas
   int fontSize = 10                // input : Kích thước text vẽ lên ảnh, mặc định là 10
)
{
   // Tạo đối tượng graphic từ ảnh bitmap
   using (Graphics graphics = Graphics.FromImage(image))
   {
      // Định nghĩa font và size vẽ
      using (Font font = new Font(fontName, fontSize))
      {
         using (Brush brush = new SolidBrush(textColor))
         {
            // Vẽ text lên ảnh
            graphics.DrawString(textContent, font, brush, textPosition);
         }
      }
   }
}
============

lưu ảnh bitmap ============
// Note   : Nên clone ra 1 ảnh trước khi thực hiện gọi hàm lưu
// Example:
//    string image_dest_path  = "path/to/your/image.jpg"
//    Bitmap your_clone_image = (Bitmap) image24Bgr.Clone();
//    SaveBitmap(your_clone_image, image_dest_path, ImageFormat.Jpeg);
//    if(your_clone_image != null) your_clone_image.Dispose();
public bool SaveBitmap(
   Bitmap bitmap,     // input : Ảnh Bitmap
   string filePath,   // input : Đường dẫn ảnh cần lưu
   ImageFormat format // input : Format ảnh cần lưu
)
{
   // Xử lý trường
   if (bitmap == null)
   {
      // Todo: Xử lý trường hợp ảnh input không hợp lệ
      // ............ PUT YOUR CODE HERE ...............
      // ...............................................
      return false;
   }

   if (string.IsNullOrWhiteSpace(filePath))
   {
      // Todo: Xử lý trường hợp đường dẫn ảnh không hợp lệ
      // ............ PUT YOUR CODE HERE ...............
      // ...............................................
      return false;
   }

   if (format == null)
   {
      // Todo: Xử lý trường hợp image format không hợp lệ
      // ............ PUT YOUR CODE HERE ...............
      // ...............................................

      // For example: Nếu user pass null thì đặt format mặc định là JPG
      format = ImageFormat.Jpeg;
   }

   // Thực hiện lưu ảnh
   bitmap.Save(filePath, format);
   return true;
}
============

diffenceBmp = |imageBmp1-imageBmp2| ============
// Note : imageBmp1 và imageBmp2 phải có CÙNG KÍCH THƯỚC, và cùng kiểu dữ liệu (Cùng là ảnh BGR (24 bit) hoặc cùng là ảnh Gray (8 bit))
void difference_image(
   Bitmap imageBmp1,        // input: Ảnh thứ nhất
   Bitmap imageBmp2,        // input: Ảnh thứ hai
   out Bitmap differentBmp  // input: Ảnh difference
)
{
   // 1. Chuyển đổi ảnh bitmap sang ảnh mat
   Mat mat1         = imageBmp1.ToMat();
   Mat mat2         = imageBmp2.ToMat();
   Mat differentMat = new Mat();

   // 2. Thực hiện kiểm tra kích thước, kiểu dữ liệu ....
   if(mat1.Size() != mat2.Size() || mat1.Channels() != mat2.Channels())
   {
      // TODO: Thực hiện xử lý ảnh đầu vào không cùng size hoặc không cùng kiểu dữ liệu
      // thường thì kết thúc hàm ở đây
      differentBmp = null;
      return;
   }

   // 3. Thực hiện tìm sự khác biệt giữa hai ảnh
   Cv2.Absdiff(mat1, mat2, differentMat);

   // 4. Chuyển đổi ngược về ảnh Bitmap
   differentBmp = differentMat.ToBitmap();
}
============

diffenceBmp = imageBmp1 - imageBmp2 ============
// Note: Các giá trị sau khi bị trừ có giá trị âm thì sẽ được chuyển về bằng 0
void minus_image(
   Bitmap imageBmp1,        // input: Ảnh thứ nhất
   Bitmap imageBmp2,        // input: Ảnh thứ hai
   out Bitmap differentBmp  // input: Ảnh difference
)
{
   // 1. Chuyển đổi ảnh bitmap sang ảnh mat
   Mat mat1         = imageBmp1.ToMat();
   Mat mat2         = imageBmp2.ToMat();
   Mat differentMat = new Mat();

   // 2. Thực hiện kiểm tra kích thước, kiểu dữ liệu ....
   if (mat1.Size() != mat2.Size() || mat1.Channels() != mat2.Channels())
   {
      // TODO: Thực hiện xử lý ảnh đầu vào không cùng size hoặc không cùng kiểu dữ liệu
      // thường thì kết thúc hàm ở đây
      differentBmp = null;
      return;
   }

   // 3. Thực hiện tìm sự khác biệt giữa hai ảnh
   Cv2.Subtract(mat1, mat2, differentMat);

   // 4. Chuyển đổi ngược về ảnh Bitmap
   differentBmp = differentMat.ToBitmap();
}
============

sumBmp = imageBmp1 + imageBmp2 ============
// Note: Các giá trị sau khi bị trừ có giá trị âm thì sẽ được chuyển về bằng 255
void sum_image(
   Bitmap imageBmp1,  // input: Ảnh thứ nhất
   Bitmap imageBmp2,  // input: Ảnh thứ hai
   out Bitmap sumBmp  // input: Ảnh difference
)
{
   // 1. Chuyển đổi ảnh bitmap sang ảnh mat
   Mat mat1   = imageBmp1.ToMat();
   Mat mat2   = imageBmp2.ToMat();
   Mat sumMat = new Mat();

   // 2. Thực hiện kiểm tra kích thước, kiểu dữ liệu ....
   if (mat1.Size() != mat2.Size() || mat1.Channels() != mat2.Channels())
   {
      // TODO: Thực hiện xử lý ảnh đầu vào không cùng size hoặc không cùng kiểu dữ liệu
      // thường thì kết thúc hàm ở đây
      sumBmp = null;
      return;
   }

   // 2. Thực hiện tìm sự khác biệt giữa hai ảnh
   Cv2.Add(mat1, mat2, sumMat);

   // 3. Chuyển đổi ngược về ảnh Bitmap
   sumBmp = sumMat.ToBitmap();
}
============

clone ROI dùng bitmap ============
void clone_roi_bitmap()
{
   // 1. Đọc ảnh
   Bitmap originalImage = new Bitmap("path/to/your/image.jpg");

   // 2. Định nghĩa tọa độ vùng ROI
   int x             = 100;  // x-coordinate of the top-left corner of the ROI
   int y             = 100;  // y-coordinate of the top-left corner of the ROI
   int width         = 200;  // Width of the ROI
   int height        = 150;  // Height of the ROI
   Rectangle roiRect = new Rectangle(x, y, width, height);

   // 3. Điều chỉnh lại vùng ROI nếu không hợp lệ (Các tọa độ của vùng ROI không ở trong ảnh)
   // Tùy mỗi bài toán có thể có các cách xử lý ROI không hợp lệ khác nhau.
   // Code dưới đây là 1 ví dụ xử lý fit vùng ROI vào trọn trong ảnh nếu tọa độ không hợp lệ

   // 3.1 Trường hợp tọa độ topleft ROI vượt khỏi ảnh
   if(roiRect.X >= originalImage.Width || roiRect.Y >= originalImage.Height)
   {
      // Todo: Cần xử lý trường hợp tọa độ Topleft roi nằm ngoài ảnh
      // Cách phổ biến là thông báo cho user và kết thúc hàm ở đây
      // Do nếu xảy ra trường hợp này thì vùng ROI không hợp lệ
      return;
   }

   // 3.2 Trường hợp Top Left ROI nhận tọa độ âm
   if(roiRect.X < 0)
      roiRect.X = 0;
   if(roiRect.Y < 0)
      roiRect.Y = 0;

   // 3.3 Trường hợp Bottom Right ROI nhận tọa độ vượt quá kích thước ảnh
   if(roiRect.X + width > originalImage.Width - 1)
      roiRect.Width  = originalImage.Width - 1 - roiRect.X;
   if(roiRect.Y + height > originalImage.Height - 1)
      roiRect.Height = originalImage.Height - 1 - roiRect.Y ;

   // 4. Tạo ảnh bitmap ROI
   Bitmap roiImage = originalImage.Clone(roiRect, originalImage.PixelFormat);

   // 5. Thêm code xử lý logic với vùng ROI
   // .....................................
   // .....................................
   // PUT YOUR LOGIC CODE HERE
   // .....................................
   // .....................................

   // 6. Giải phóng tài nguyên nếu không dùng nữa
   if(originalImage != null)
      originalImage.Dispose();
   if(roiImage != null)
      roiImage.Dispose();
}
============

vẽ Rectangle lên bitmap ============
// Note: Hàm này vẽ trực tiếp lên ảnh đầu vào nên cần clone ảnh trước khi pass vào hàm này nếu muốn giữ nguyên ảnh gốc
void draw_rectangle_on_bitmap(
   ref Bitmap image,  // inout : Ảnh input gốc
   Rectangle rect,    // input : Rectangle cần vẽ lên ảnh
   Color color,       // input : Màu text
   int thickness = 1  // input : Độ dày của đường vẽ
)
{
   // Tạo đối tượng graphic từ ảnh bitmap
   using (Graphics g = Graphics.FromImage(image))
      {
         // Create a Pen object with black color and width
         using (Pen pen = new Pen(color, thickness))
         {
            // Draw the rectangle on the bitmap
            g.DrawRectangle(pen, rect);
         }
      }
}
============

 

access pixel ảnh Mat ============
void access_to_pixel_opencvsharp()
{
   // 1. Đọc ảnh
   Mat imageMatBgr24  = new Mat("put/your/image/path/here");

   // 2. Duyệt qua từng pixel của ảnh
   unsafe
   {
      byte* imagePtr  = (byte*)imageMatBgr24.Data;
      int imageWidth  = imageMatBgr24.Width;
      int imageHeight = imageMatBgr24.Height;
      int imageStep   = (int)imageMatBgr24.Step();

      // Thực hiện duyệt qua từng pixel của ảnh
      for (int y = 0; y < imageHeight; y++)
      {
         for (int x = 0; x < imageWidth; x++)
         {
            // Access BGR channels of each pixel
            byte blue  = imagePtr[y * imageStep + x * 3];
            byte green = imagePtr[y * imageStep + x * 3 + 1];
            byte red   = imagePtr[y * imageStep + x * 3 + 2];

            // Todo: Thực hiện logic với từng pixel của ảnh ở đây
            // Ví dụ: in ra giá trị ảnh để debug
            Console.WriteLine($"Pixel at ({x},{y}): B={(int)blue} G={(int)green} R={(int)red}");
         }
      }
   }

   // 3. Kết thúc hàm. Giải phóng resource nếu không dùng nữa
   if(imageMatBgr24 != null)
   imageMatBgr24.Dispose();
}

============

clone ROI dùng ảnh Mat ============
void clone_roi_opencvsharp()
{
   // 1. Đọc ảnh
   Mat originalImage = new Mat("path/to/your/image.jpg");

   // 2. Định nghĩa tọa độ vùng ROI
   int x        = 100;  // x-coordinate of the top-left corner of the ROI
   int y        = 100;  // y-coordinate of the top-left corner of the ROI
   int width    = 200;  // Width of the ROI
   int height   = 150;  // Height of the ROI
   Rect roiRect = new Rect(x, y, width, height);

   // 3. Điều chỉnh lại vùng ROI nếu không hợp lệ (Các tọa độ của vùng ROI không ở trong ảnh)
   // Tùy mỗi bài toán có thể có các cách xử lý ROI không hợp lệ khác nhau.
   // Code dưới đây là 1 ví dụ xử lý fit vùng ROI vào trọn trong ảnh nếu tọa độ không hợp lệ

   // 3.1 Trường hợp tọa độ topleft ROI vượt khỏi ảnh
   if(roiRect.X >= originalImage.Width || roiRect.Y >= originalImage.Height)
   {
      // Todo: Cần xử lý trường hợp tọa độ Topleft roi nằm ngoài ảnh
      // Cách phổ biến là thông báo cho user và kết thúc hàm ở đây
      // Do nếu xảy ra trường hợp này thì vùng ROI không hợp lệ
      return;
   }

   // 3.2 Trường hợp Top Left ROI nhận tọa độ âm
   if(roiRect.X < 0)
      roiRect.X = 0;
   if(roiRect.Y < 0)
      roiRect.Y = 0;

   // 3.3 Trường hợp Bottom Right ROI nhận tọa độ vượt quá kích thước ảnh
   if(roiRect.X + width > originalImage.Width - 1)
      roiRect.Width  = originalImage.Width - 1 - roiRect.X;
   if(roiRect.Y + height > originalImage.Height - 1)
      roiRect.Height = originalImage.Height - 1 - roiRect.Y ;

   // 4. Tạo ảnh bitmap ROI
   Mat roiImage = new Mat(originalImage, roiRect).Clone();
   // Nếu không clone ra thì bất cứ thay đổi nào trên ảnh ROI sẽ được áp dụng cho ảnh originalImage


   // 5. Thêm code xử lý logic với vùng ROI
   // .....................................
   // .....................................
   // PUT YOUR LOGIC CODE HERE
   // .....................................
   // .....................................

   // 6. Giải phóng tài nguyên nếu không dùng nữa
   if(originalImage != null)
      originalImage.Dispose();
   if(roiImage != null)
      roiImage.Dispose();
}
============

Copyright©2016 Machine Imagination Technologies. All rights reserved.