Перейти к содержимому
Compvision.ru

Sergiy01

Пользователи
  • Количество публикаций

    2
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные пользователем Sergiy01


  1. Доброе время суток! Необходимо распознать автомобильный номер на изображении, для увеличения точности решил трансформировать номер так, будто камера смотрит прямо на него. Для выполнения задачи решил найти верхнюю и левую линии, и из них рассчитать углы, но столкнулся с проблемой.

    Метод CvInv oke.HoughLines находит большое количество линий, но даже при увеличении порога правильная линия попадается редко.Hough.png.1b18d3812ec336cd8e6305f910bf331e.png

    Написал аналог данного метода C# но для поиска только самой явной линии, однако он страдает той же проблемой.MyHough.png.cca65a5c3bcb6f5f4aec7638f4c348cc.png

    Разница где то в 15 градусов, если "докинуть" их вручную выходит почти правильно.MyHoughPlus15.png.621b7b8502c552a82a5c839e942e5a05.png

    За основу алгоритма был взят CvInv oke.HoughLines, сам метод:

    public static unsafe LineSegment2D FindBestLineD(Mat input, double minTheta, double maxTheta, double theta, int rho)
            {
                int width = input.Width;
                int height = input.Height;

                int max_rho = (int)Math.Sqrt(width * width + height * height);
                int min_rho = -max_rho;

                int thetaCount = (int)((maxTheta - minTheta) / theta);
                int rhoCount = (int)(((max_rho - min_rho) + 1) / rho);

                double[] thetaArr = new double[thetaCount];
                double tmp = minTheta;

                double[] sinTheta = new double[thetaCount];
                double[] cosTheta = new double[thetaCount];

                for (int i = 0; i < thetaCount; i++)
                {
                    thetaArr = tmp;
                    sinTheta = Math.Sin(tmp);
                    cosTheta = Math.Cos(tmp);

                    tmp += theta;
                }

                int[,] accum = new int[rhoCount, thetaCount];

                Bitmap bitmap = input.Bitmap;
                BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);

                byte* Pixels = (byte*)bitmapData.Scan0.ToPointer();
                int stride = bitmapData.Stride;
                int shift = 0;

                for (int h = 0; h < height; h++)
                {
                    shift = stride * h;
                    for (int w = 0; w < width; w++)
                    {
                        if (Pixels[shift + w] != 0)
                        {
                            for (int i = 0; i < thetaCount; i++)
                            {
                                int r = (int)(h * sinTheta + w * cosTheta);
                                r += rhoCount / 2;
                                accum[r, i]++;
                            }
                        }
                    }
                }

                bitmap.UnlockBits(bitmapData);

                int MaxValue = 0;
                int BestRho = 0;
                double BestTheta = 0;

                for (int t = 0; t < thetaArr.Length; t++)
                {
                    for (int r = 0; r < rhoCount; r++)
                    {
                        if (accum[r, t] > MaxValue)
                        {
                            MaxValue = accum[r, t];
                            BestTheta = thetaArr[t];
                            BestRho = r - rhoCount / 2;
                        }
                    }
                }
                //BestTheta += theta * 15;
                var pt1 = new Point();
                var pt2 = new Point();
                var a = Math.Cos(BestTheta);
                var b = Math.Sin(BestTheta);
                var x0 = a * BestRho;
                var y0 = b * BestRho;
                pt1.X = (int)Math.Round(x0 + input.Width * (-b));
                pt1.Y = (int)Math.Round(y0 + input.Height * (a));
                pt2.X = (int)Math.Round(x0 - input.Width * (-b));
                pt2.Y = (int)Math.Round(y0 - input.Height * (a));
                return new LineSegment2D(pt1, pt2);
            }

    Если бы проблема была только с ним, продолжал бы сам искать ошибку, но предложенный в библиотеке вариант тоже "недокручивает" градусы.

    Есть ли у кого предположение с чем может быть связан данный феномен, может ли быть тому причиной малый размер изображения (ширина до 200 px )? Или может существуют более удобные решения данной проблемы, при условии что быстродействие является критичным?

×