بنظرتون با الگوریتم Sobel که برای لبه یابی هست میشه کاراکتر هارو جدا کرد؟ با سوبل قشنگ دور هر چیزی رو با رنگ سفید متمایز میکنه حالا چطور جدا شون کنیم به طوری که ترتیبشون توی کلمات حفظ بشه؟
اینم کد سوبل:
اینم منبع و برنامه به زبان سی شارپ:
http://behsanandish.com/learning/ips...matlab-c-vbcc/
کد الگوریتم سوبل( Sobel ) در #C:
using System;using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace SobelOperator
{
public partial class Sobel : Form
{
OpenFileDialog ofd;
SaveFileDialog sfd;
Bitmap bmp;
public Sobel()
{
InitializeComponent();
ofd = new OpenFileDialog();
sfd = new SaveFileDialog();
}
private Bitmap cbmp
{
get
{
if (bmp == null)
{
bmp = new Bitmap(1, 1);
}
return bmp;
}
set
{
bmp = value;
}
}
private void save(string filepath)
{
if (System.IO.File.Exists(filepath))
{
System.IO.File.Delete(filepath);
}
bmp.Save(filepath);
}
//Sobel operator kernel for horizontal pixel changes
private static double[,] xSobel
{
get
{
return new double[,]
{
{ -1, 0, 1 },
{ -2, 0, 2 },
{ -1, 0, 1 }
};
}
}
//Sobel operator kernel for vertical pixel changes
private static double[,] ySobel
{
get
{
return new double[,]
{
{ 1, 2, 1 },
{ 0, 0, 0 },
{ -1, -2, -1 }
};
}
}
private static Bitmap ConvolutionFilter(Bitmap sourceImage, double[,] xkernel, double[,] ykernel, double factor = 1, int bias = 0, bool grayscale = false)
{
//Image dimensions stored in variables for convenience
int width = sourceImage.Width;
int height = sourceImage.Height;
//Lock source image bits into system memory
BitmapData srcData = sourceImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
//Get the total number of bytes in your image - 32 bytes per pixel x image width x image height -> for 32bpp images
int bytes = srcData.Stride * srcData.Height;
//Create byte arrays to hold pixel information of your image
byte[] pixelBuffer = new byte[bytes];
byte[] resultBuffer = new byte[bytes];
//Get the address of the first pixel data
IntPtr srcScan0 = srcData.Scan0;
//Copy image data to one of the byte arrays
Marshal.Copy(srcScan0, pixelBuffer, 0, bytes);
//Unlock bits from system memory -> we have all our needed info in the array
sourceImage.UnlockBits(srcData);
//Convert your image to grayscale if necessary
if (grayscale == true)
{
float rgb = 0;
for (int i = 0; i < pixelBuffer.Length; i += 4)
{
rgb = pixelBuffer[i] * .21f;
rgb += pixelBuffer[i + 1] * .71f;
rgb += pixelBuffer[i + 2] * .071f;
pixelBuffer[i] = (byte)rgb;
pixelBuffer[i + 1] = pixelBuffer[i];
pixelBuffer[i + 2] = pixelBuffer[i];
pixelBuffer[i + 3] = 255;
}
}
//Create variable for pixel data for each kernel
double xr = 0.0;
double xg = 0.0;
double xb = 0.0;
double yr = 0.0;
double yg = 0.0;
double yb = 0.0;
double rt = 0.0;
double gt = 0.0;
double bt = 0.0;
//This is how much your center pixel is offset from the border of your kernel
//Sobel is 3x3, so center is 1 pixel from the kernel border
int filterOffset = 1;
int calcOffset = 0;
int byteOffset = 0;
//Start with the pixel that is offset 1 from top and 1 from the left side
//this is so entire kernel is on your image
for (int OffsetY = filterOffset; OffsetY < height - filterOffset; OffsetY++)
{
for (int OffsetX = filterOffset; OffsetX < width - filterOffset; OffsetX++)
{
//reset rgb values to 0
xr = xg = xb = yr = yg = yb = 0;
rt = gt = bt = 0.0;
//position of the kernel center pixel
byteOffset = OffsetY * srcData.Stride + OffsetX * 4;
//kernel calculations
for (int filterY = -filterOffset; filterY <= filterOffset; filterY++)
{
for (int filterX = -filterOffset; filterX <= filterOffset; filterX++)
{
calcOffset = byteOffset + filterX * 4 + filterY * srcData.Stride;
xb += (double)(pixelBuffer[calcOffset]) * xkernel[filterY + filterOffset, filterX + filterOffset];
xg += (double)(pixelBuffer[calcOffset + 1]) * xkernel[filterY + filterOffset, filterX + filterOffset];
xr += (double)(pixelBuffer[calcOffset + 2]) * xkernel[filterY + filterOffset, filterX + filterOffset];
yb += (double)(pixelBuffer[calcOffset]) * ykernel[filterY + filterOffset, filterX + filterOffset];
yg += (double)(pixelBuffer[calcOffset + 1]) * ykernel[filterY + filterOffset, filterX + filterOffset];
yr += (double)(pixelBuffer[calcOffset + 2]) * ykernel[filterY + filterOffset, filterX + filterOffset];
}
}
//total rgb values for this pixel
bt = Math.Sqrt((xb * xb) + (yb * yb));
gt = Math.Sqrt((xg * xg) + (yg * yg));
rt = Math.Sqrt((xr * xr) + (yr * yr));
//set limits, bytes can hold values from 0 up to 255;
if (bt > 255) bt = 255;
else if (bt < 0) bt = 0;
if (gt > 255) gt = 255;
else if (gt < 0) gt = 0;
if (rt > 255) rt = 255;
else if (rt < 0) rt = 0;
//set new data in the other byte array for your image data
resultBuffer[byteOffset] = (byte)(bt);
resultBuffer[byteOffset + 1] = (byte)(gt);
resultBuffer[byteOffset + 2] = (byte)(rt);
resultBuffer[byteOffset + 3] = 255;
}
}
//Create new bitmap which will hold the processed data
Bitmap resultImage = new Bitmap(width, height);
//Lock bits into system memory
BitmapData resultData = resultImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
//Copy from byte array that holds processed data to bitmap
Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length);
//Unlock bits from system memory
resultImage.UnlockBits(resultData);
//Return processed image
return resultImage;
}
private void btnLoad_Click(object sender, EventArgs e)
{
if (ofd.ShowDialog() == DialogResult.OK)
{
bmp = (Bitmap)Bitmap.FromFile(ofd.FileName);
AutoScroll = true;
AutoScrollMinSize = new Size(Convert.ToInt32(bmp.Width), Convert.ToInt32(bmp.Height));
Invalidate();
}
}
private void btnSave_Click(object sender, EventArgs e)
{
if (sfd.ShowDialog() == DialogResult.OK)
{
save(sfd.FileName);
}
}
private void btnSobel_Click(object sender, EventArgs e)
{
bmp = ConvolutionFilter(bmp, xSobel, ySobel, 1.0, 0, true);
Invalidate();
}
private void Display(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(cbmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
}
}
}
همه این کد در اینجا موجود است (پروژه با ویژوال استودیو ۲۰۱۵ ایجاد شد):
SobelOperatorInC#
رمز فایل : behsanandish.com