C# 将多个数字的图像分割为只有一个数字的单独图像
我正在尝试将手写数字的图像分割为单独的数字 假设我有这样的形象: 我做了一个简单的逻辑,可以工作,但它会,它确实遇到了一个问题:C# 将多个数字的图像分割为只有一个数字的单独图像,c#,image,image-processing,C#,Image,Image Processing,我正在尝试将手写数字的图像分割为单独的数字 假设我有这样的形象: 我做了一个简单的逻辑,可以工作,但它会,它确实遇到了一个问题: private static void SplitImages() { //We're going to use this code once.. to split our own images into seperate images.. can we do this somehow? Bitmap testSplitImage = (Bitmap
private static void SplitImages()
{
//We're going to use this code once.. to split our own images into seperate images.. can we do this somehow?
Bitmap testSplitImage = (Bitmap)Bitmap.FromFile("TestSplitImage.jpg");
int[][] imagePixels = new int[testSplitImage.Width][];
for(int i=0;i<imagePixels.Length;i++)
{
imagePixels[i] = new int[testSplitImage.Height];
}
for(int i=0;i<imagePixels.Length;i++)
{
for(int j=0;j<imagePixels[i].Length;j++)
{
Color c = testSplitImage.GetPixel(i, j);
imagePixels[i][j] = (c.R + c.G + c.B) / 3;
}
}
//let's start by getting the first height vector... and count how many of them is white..dunno..
int startColNumber = 0;
int endColNumber = 0;
bool isStart = false;
int imageNumber = 1;
for(int i=0;i<imagePixels.Length;i++)
{
int whiteNumbers = 0;
for(int j=0;j<imagePixels[i].Length;j++)
{
if (imagePixels[i][j] > 200)
{
//consider it white or not really relevant
whiteNumbers++;
}
}
if (whiteNumbers > testSplitImage.Height*95.0/100.0)
{
//let's consider that if a height vector has more than 95% white pixels.. it means that we can start checking for an image
//now if we started checking for the image.. we need to stop
if (isStart)
{
//consider the end of image.. so the end column should be here or we make it +1 at least
endColNumber = i + 1;
isStart = false;
}
}
else
{
if (!isStart)
{
isStart = true; //we will start checking for the image one row before that maybe?
startColNumber = i == 0 ? i : i - 1;
}
}
if (endColNumber > 0)
{
//we got a start and an end.. let's create a new image out of those pixels..hopefully this will work
Bitmap splittedImage = new Bitmap(endColNumber - startColNumber + 1, testSplitImage.Height);
int col = 0;
for(int k=startColNumber;k<=endColNumber;k++)
{
for (int l=0;l<testSplitImage.Height;l++)
{
int c = imagePixels[k][l];
splittedImage.SetPixel(col, l, Color.FromArgb(c, c, c));
}
col++;
}
splittedImage.Save($"Image{imageNumber++}.jpg");
endColNumber = 0;
}
whiteNumbers = 0;
}
}
private static void SplitImages()
{
//我们将使用此代码一次..将我们自己的图像分割为单独的图像..我们能以某种方式做到这一点吗?
位图testSplitImage=(位图)Bitmap.FromFile(“testSplitImage.jpg”);
int[][]imagePixels=新int[testSplitImage.Width][];
对于(int i=0;i 0)
{
//我们有了一个开始和一个结束。让我们用这些像素创建一个新的图像。希望这能起作用
位图splittedImage=新位图(endColNumber-startColNumber+1,testSplitImage.Height);
int col=0;
对于(int k=startColNumber;k此代码仅适用于单色(两种颜色,黑色和白色)图像
公共静态类处理器
{
公共静态字节[]ToArray(此位图bmp)//使用锁位的位图到字节数组
{
矩形rect=新矩形(0,0,bmp.Width,bmp.Height);
BitmapData data=bmp.LockBits(rect,ImageLockMode.ReadWrite,bmp.PixelFormat);
IntPtr ptr=data.Scan0;
int numBytes=data.Stride*bmp.Height;
字节[]字节=新字节[numBytes];
System.Runtime.InteropServices.Marshal.Copy(ptr,bytes,0,numBytes);
解锁位(数据);
返回字节;
}
public static int GetPixel(这个字节[]数组,int bpr,int x,int y)//找出给定的像素是0还是1
{
int num=y*bpr+x/8;
返回(数组[num]>>7-x%8)&1;
}
公共静态列表getDrawingPoints(此点开始,字节[]数组,int-width,int-height)//获取一个0点(黑点)并通过移动邻居查找所有相邻的黑点
{
列表点=新列表();
点。添加(开始);
int BytePerRow=array.Length/bmp.Height;
int计数器=0;
做
{
对于(int i=Math.Max(0,点[counter].X-1);i p.X).First().X,
endX=points.OrderByDescending(p=>p.X).First().X,
startY=points.OrderBy(p=>p.Y).First().Y,
endY=points.OrderByDescending(p=>p.Y).First().Y;
位图bmp=新位图(endX-startX+1,endY-startY+1);
Graphics g=Graphics.FromImage(bmp);
g、 FillRectangle(新的SolidBrush(Color.White),新的矩形(0,0,endX-startX-1,endY-startY-1));
对于(int i=startY;i p.X==i&p.Y==j))
{
列表点=新点(i,j).getDrawingPoints(数组,bmp.Width,bmp.Height);
已处理。添加范围(点);
位图结果=points.ToBitmap();
Save($“{imgIndex++}.bmp”);
}
}
我正在使用绘画和另存为单色bmp格式生成源图像
我还用这张图片测试了它:
这将产生以下三幅图像:
发生这种情况的原因是3和7在同一列中都有一个黑点,我以前做过这方面的工作,但由于我现在没有时间编写代码,我只想给出一个想法,在找到一个黑点后,您应该检查它的邻居,添加所有的黑点,然后检查添加点的邻居,依此类推直到你找不到任何黑人邻居。如果你在数组中加载图像(搜索锁位)这将比逐像素处理快上千倍。到今天结束时,我将尝试添加一个答案。感谢@AshkanMobayenKhiabani提供的信息。我会调查这一点并回复你。感谢你的时间,我将根据我目前拥有的图像进行测试,然后回复给你。所有图像都已经是黑白的re(希望我没有弄错)。我得到了一些非常奇怪的结果。我真的无法解释我得到了什么。我确实尝试过将它保存为来自绘画的单色bmp图像,并得到了更奇怪的东西。我会看看你的代码,也许我可以找到问题的原因。它实际上对我自己的测试文件起作用。很好,但是的,对你的测试文件进行了尝试,得到了奇怪的结果,让我检查一下很抱歉,这行代码重复了2次:`int BytePerRow=(int)Math.Ceiling((双)宽/8);`once in Process.cs和once in main code。请将两者更改为:int BytePerRow=array.Length/Bmp.Height;
和int BytePerRow=array.Length/Height;
。这是因为有时锁位会向字节数组taht添加一些空的额外字节,从而导致BytesPerRow的计算错误。只需更改计算方式即可。I also添加了一个我测试代码时使用的图像,这是为了表明,不管字母的x或y是否相同,但这仍然可以将它们分开。我用我的图像进行了测试,得到了很好的结果。再次感谢您的时间。我将通过我的4K图像运行它。在将它们转换为单色位图图像后..不知何故。
public static class Processor
{
public static byte[] ToArray(this Bitmap bmp) // bitmap to byte array using lockbits
{
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData data = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
IntPtr ptr = data.Scan0;
int numBytes = data.Stride * bmp.Height;
byte[] bytes = new byte[numBytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, bytes, 0, numBytes);
bmp.UnlockBits(data);
return bytes;
}
public static int GetPixel(this byte[] array, int bpr, int x, int y) //find out if the given pixel is 0 or 1
{
int num = y * bpr + x / 8;
return (array[num] >> 7- x%8) & 1;
}
public static List<Point> getDrawingPoints(this Point start, byte[] array, int width, int height) // get one 0 point (black point) and find all adjacent black points by traveling neighbors
{
List<Point> points = new List<Point>();
points.Add(start);
int BytePerRow = array.Length / bmp.Height;
int counter = 0;
do
{
for (int i = Math.Max(0, points[counter].X - 1); i <= Math.Min(width - 1, points[counter].X + 1); i++)
for (int j = Math.Max(0, points[counter].Y - 1); j <= Math.Min(height - 1, points[counter].Y + 1); j++)
if (array.GetPixel(BytePerRow, i, j) == 0 && !points.Any(p => p.X == i && p.Y == j))
points.Add(new Point(i, j));
counter++;
} while (counter < points.Count);
return points;
}
public static Bitmap ToBitmap(this List<Point> points) // convert points to bitmap
{
int startX = points.OrderBy(p => p.X).First().X,
endX = points.OrderByDescending(p => p.X).First().X,
startY = points.OrderBy(p => p.Y).First().Y,
endY = points.OrderByDescending(p => p.Y).First().Y;
Bitmap bmp = new Bitmap(endX - startX + 1, endY - startY + 1);
Graphics g = Graphics.FromImage(bmp);
g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, endX - startX - 1, endY - startY - 1));
for (int i = startY; i <= endY; i++)
for (int j = startX; j <= endX; j++)
if (points.Any(p => p.X == j && p.Y == i)) bmp.SetPixel(j - startX, i - startY, Color.Black);
return bmp;
}
}
List<Point> processed = new List<Point>();
Bitmap bmp = ((Bitmap)Bitmap.FromFile(SourceBitmapPath));
byte[] array = bmp.ToArray();
int BytePerRow = array.Length / bmp.Height;
int imgIndex = 1;
for (int i = 0; i < bmp.Width; i++)
for (int j = 0; j < bmp.Height; j++)
{
if (array.GetPixel(BytePerRow, i, j) == 0 && !processed.Any(p => p.X == i && p.Y == j))
{
List<Point> points = new Point(i, j).getDrawingPoints(array, bmp.Width, bmp.Height);
processed.AddRange(points);
Bitmap result = points.ToBitmap();
result.Save($"{imgIndex++}.bmp");
}
}