Image Processing İşlemleri Kullanımı
Husamettin Elalmis
Last updated
Husamettin Elalmis
Last updated
Merhaba arkadaşlar, bu yazıda sizlere basit düzeyde Image Processing işlemlerinin nasıl yapılabileceğini anlatacağım.
Kullanılan Kavramlar
Pixel kavramı
RGB kavramı
GrayScale kavramı
BlackWhite kavramı
Matematiksel İşlemler
Bizim frameworkte nasıl kullanabiliriz?
Optik Sınav Kağıtlarının okunmasında kullanabiliriz
Diğer amaçlar için kullanabiliriz
Örnek Proje Yapısı
Projemiz, örnek olarak Scannerdan taratılmış bir OptikFormu okuyacaktır.
Örnek olarak taranmış optikform (ad soyad yanlış işaretlenmiştir)
GrayScale (gri tonlama) yapısına dönüştürülmüş hali
BlackWhite (siyah-beyaz) formata dönüştürülmüş hali
Winform uygulamamız, optikformun orjinal halini, GrayScale halini ve BlackWhite halini göstermektedir.
Formun dikey olarak Düzgün olup olmadığı kontrolü yapılarak otomatik düzeltme işlemi yapılır
BlackWhite (siyah-beyaz) tual üzerinde mesh (bölgesel işaretleme) matrisleri oluşturularak siyah işaretlenmiş blocklar sırasıyla okunarak işaretlenmiş cevaplar birleştirilir.
ImageHelper Classı
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
namespace OptikFormArge
{
public class ImageHelper
{
// PointsInCircle - Çemberin içerisindeki noktaların koordinatlarını verir public List<Point> PointsInCircle(int x0, int y0, int radius)
{
List<Point> points = new List<Point>();
Color black = Color.FromArgb(255, 0, 0, 0);
using (Bitmap bmp = new Bitmap(radius, radius, PixelFormat.Format32bppArgb))
{
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.White);
g.FillEllipse(Brushes.Black, 0, 0, radius, radius);
}
Size size0 = bmp.Size;
Rectangle rect = new Rectangle(Point.Empty, size0);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
int size1 = bmpData.Stride * bmpData.Height; byte[] data = new byte[size1];
System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, data, 0, size1);
for (int y = 0; y < radius; y++) for (int x = 0; x < radius; x++)
{
int index = y * bmpData.Stride + x * 4; if (data[index] == 0)
{
points.Add(new Point(x0 + x, y0 + y));
}
}
}
return points;
}
// GrayScaleFilter - Imageyi grayscale veya blackwhitea çevirir public Bitmap GrayScaleFilter(Bitmap image, bool useBW)
{
Bitmap grayScale = new Bitmap(image.Width, image.Height);
for (Int32 y = 0; y < grayScale.Height; y++) for (Int32 x = 0; x < grayScale.Width; x++)
{
Color c = image.GetPixel(x, y);
Int32 gs = (Int32)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11);
if (useBW)
{
gs = gs < 100 ? 0 : 255;
grayScale.SetPixel(x, y, Color.FromArgb(gs, gs, gs));
}
else
{
grayScale.SetPixel(x, y, Color.FromArgb(gs, gs, gs));
}
}
return grayScale;
}
// RotateImage - Imageyi döndürür public Bitmap RotateImage(Bitmap bmp, float angle)
{
Bitmap rotatedImage = new Bitmap(bmp.Width, bmp.Height);
rotatedImage.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
using (Graphics g = Graphics.FromImage(rotatedImage))
{
g.TranslateTransform(bmp.Width / 2, bmp.Height / 2);
g.RotateTransform(angle);
g.TranslateTransform(-bmp.Width / 2, -bmp.Height / 2);
g.DrawImage(bmp, new Point(0, 0));
}
return rotatedImage;
}
}
}
FormuOku Button Click
// CountForBlack – Points arrayi içerisindeki noktaların sayısını pixel cinsinden sayar
private int CountForBlack(List<Point> points, Bitmap bmp)
{
int counter = 0; foreach (var item in points)
{
var pixel = bmp.GetPixel(item.X, item.Y); var colorAvg = (pixel.R + pixel.G + pixel.B) / 3; if (colorAvg <= 16) counter++;
}
return counter;
}
// btnFormuOku
private void btnFormuOku_Click(object sender, EventArgs e)
{
Bitmap bmp = (Bitmap)Image.FromFile("formbw.jpeg");
bmp = helper.RotateImage(bmp, 0.15f);
pb3.Image = bmp;
var x0 = 42; var y0 = 78; var radius = 12; var points = helper.PointsInCircle(x0, y0, radius); using (Graphics g = Graphics.FromImage(bmp))
{
// tcno string tcNo = string.Empty; for (int i = 0; i < 11; i++)
{
for (int j = 0; j < 10; j++)
{
var x = x0 + i * radius; var y = y0 + j * radius;
g.DrawRectangle(new Pen(Color.DarkOrange), new Rectangle(x, y, radius, radius));
points = helper.PointsInCircle(x, y, radius);
var countForBlack = CountForBlack(points, bmp); if (countForBlack > 20)
{
tcNo += j + 1;
}
}
}
rtb1.AppendText($"tcno:{tcNo}\n");
…
// türkçe string cevapArr = "ABCDE"; string turkce = string.Empty; var x9 = x4 + 8 * radius + radius / 4; var y9 = y0 - 1 * radius; for (int j = 0; j < 40; j++)
{
for (int i = 0; i < 5; i++)
{
var x = x9 + i * radius; var y = y9 + j * radius;
g.DrawRectangle(new Pen(Color.DeepSkyBlue), new Rectangle(x, y, radius, radius));
points = helper.PointsInCircle(x, y, radius);
var countForBlack = CountForBlack(points, bmp); if (countForBlack > 20)
{
turkce += cevapArr[i];
}
}
}
var s = "Türkçe Testi";
rtb1.AppendText($"{s}:{turkce}\n");
…
}
Okuma sonuçları richtextboxda gösterilmiştir
Sonuç
Bitmap üzerindeki işlemler için, Pixel, GrayScale ve BlackWhite kavramları kullanılarak buna benzer senaryolara ilişkin çözümler geliştirilebilir
Metin okuma, cisim algılama vb. diğer yöntemler için librarynin geliştirilmesi gerekmektedir.
Saygılarımla,
Hüsamettin ELALMIŞ – 26.06.2021
husamettin.elalmis@arksoft.com.tr