Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将多个数字的图像分割为只有一个数字的单独图像_C#_Image_Image Processing - Fatal编程技术网

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");
           }

      }