Как исправить искаженное изображение для распознавания?

#c# #opencv #emgucv

#c# #opencv #emgucv

Вопрос:

Я только начал проект распознавания текста несколько недель назад. Я застрял с проблемой искажения изображения, я перепробовал много разных методов, кажется, ничего не работает, так что, пожалуйста, помогите 🙂

Искаженное изображение приведено ниже

искаженная ссылка на изображение

Я хочу, чтобы окончательное изображение было таким, как указано ниже

окончательное изображение по мере необходимости

Я уже пытался изменить изображение, но не смог получить окончательное изображение.

 public Image<Gray, byte> ImageDeskewOuter(Image<Gray, byte> img)
{
    img = img.Resize(img.Height, img.Width, Inter.Linear);
    Image<Gray, byte> tmp = new Image<Gray, byte>(img.Bitmap);
    tmp = tmp.ThresholdToZero(new Gray(180));

    int nZero = tmp.CountNonzero()[0] == 0 ? 1 : tmp.CountNonzero()[0];
    if (tmp.Bytes.Length / nZero < 10)
        img = tmp.Not();
    else
        img = img.ThresholdToZero(new Gray(80)).InRange(new Gray(0), new Gray(60)).Not();
    tmp = new Image<Gray, byte>(img.Bitmap).Canny(50, 150);

    List<Rectangle> rlist = new List<Rectangle>();
    Rectangle min = new Rectangle();
    Rectangle max = new Rectangle();
    VectorOfVectorOfPoint contour = new VectorOfVectorOfPoint();
    Mat hier = new Mat();
    CvInvoke.FindContours(tmp, contour, hier, RetrType.External, ChainApproxMethod.ChainApproxSimple);
    if (contour.Size > 0)
    {
        for (int i = 0; i < contour.Size; i  )
        {
            Rectangle rec = CvInvoke.BoundingRectangle(contour[i]);
            if (rec.Width > 30 amp;amp; rec.Width < 120 amp;amp; rec.Height > 50 amp;amp; rec.Height < 120)
            {
                rlist.Add(rec);                        
            }
        }
        min = rlist.OrderBy(x => x.X).FirstOrDefault();
        max = rlist.OrderByDescending(x => x.X).FirstOrDefault();
        Rectangle roi = Rectangle.Union(min, max);
        img.ROI = roi;
    }
    if (rlist.Count > 0)
    {
        double angle = LineAngle(min.X, min.Bottom, max.X, max.Bottom, min.X, min.Bottom, max.X, min.Bottom)   3;
        img = img.Rotate(angle, new Gray(255), false);
    }
    return img;
}
 

Окончательное изображение с использованием вышеуказанной функции

мое изображение после использования приведенного выше кода

Комментарии:

1. #Gimby, как я объяснил выше, что я хочу изменить изображение, пожалуйста, сосредоточьтесь на этом, не переходите на следующий шаг и не выполняйте распознавание … 🙂

2. Какие библиотеки вы используете?

3. EmguCV.3.1.0.1 с помощью tesseract

Ответ №1:

Шаг 1> Выберите нужный контур и примените CvInvoke.Minarearrect() и скопируйте область изображения в новое изображение

Шаг 2> Создайте растровое изображение, ширина которого равна сумме всей ширины обрезанного изображения (если вы хотите поместить каждое изображение рядом)

Шаг 3> Использование графики для рисования изображения на растровом изображении

     public Image<Gray, byte> ImageDeskew(Image<Gray, byte> img)
    {
        img = img.Resize(img.Height, img.Width, Inter.Linear);
        Image<Gray, byte> tmp = new Image<Gray, byte>(img.Bitmap);
        tmp = new Image<Gray, byte>(AdjustContrast(tmp.Bitmap, 70));

        img = tmp.Not().ThresholdAdaptive(new Gray(255), AdaptiveThresholdType.MeanC, ThresholdType.Binary, 45, new Gray(10));
        tmp = new Image<Gray, byte>(img.Bitmap).Canny(50, 150);

         List<Image<Gray, byte>> imglist = new List<Image<Gray, byte>>();
        Rectangle min = new Rectangle();
        Rectangle max = new Rectangle();
        VectorOfVectorOfPoint contour = new VectorOfVectorOfPoint();
        Mat hier = new Mat();
        CvInvoke.FindContours(tmp, contour, hier, RetrType.External, ChainApproxMethod.ChainApproxSimple);
        if (contour.Size > 0)
        {
            for (int i = 0; i < contour.Size; i  )
            {
                RotatedRect rRect = CvInvoke.MinAreaRect(contour[i]);
                float area = rRect.Size.Width * rRect.Size.Height;
                if (area > (img.Bytes.Length / 10))
                {
                    rlist.Add(rec);
                    if (rRect.Angle > -45) imglist.Add(img.Copy(rRect));
                    else imglist.Add(img.Copy(rRect).Rotate(-90, new Gray(255), false));
                }                    
            }
        }

       
            if (imglist.Count > 0)
            {
                int xPx = imglist.Sum(x => x.Width);
                Bitmap bitmap = new Bitmap(xPx, img.Height);
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    xPx = 0;
                    imglist.Reverse();
                    foreach (Image<Gray, byte> i in imglist)
                    {
                        g.DrawImage(i.Not().Bitmap, xPx, 0);
                        xPx  = i.Width;
                    }
                }
                img = new Image<Gray, byte>(bitmap).Not();
            }
        
        return img;
    }