С Новым годом! Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.52/21: Рейтинг темы: голосов - 21, средняя оценка - 4.52
0 / 0 / 0
Регистрация: 23.04.2016
Сообщений: 11

Emgu cv. Изометрия окружности

24.04.2016, 12:02. Показов 4511. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Прошу подсказки, в какую сторону копать. Суть вопроса: на вход подается фотография окружности сделанная откуда-нибудь сбоку, сверху и т.п. К окружности (при фотографировании) подставлена "шахматка" (листок с шахматной клеткой), которая должна помочь в преобразовании изображения. Необходимо преобразовать фотографию из исходного вида во фронтальный. Подойдет любая информация, будь то раздел геометрии, который можно почитать или функции библиотеки emgu cv. Надеюсь вопрос объяснил понятно. Спасибо за внимание.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
24.04.2016, 12:02
Ответы с готовыми решениями:

Изометрия
Нужна помощь. Как работать с изометрией в C++ Builder? Сделать хочу простенькую игру: Перемещение по карте, взаимодействие с обьектами....

Изометрия клик мыши
Доброго всем времени суток у нас на форуме нет ветки про игры на HTML и JS поэтому выбрал так сказать более менее приближённую ветку. У...

Изометрия в играх на C++/SFML
Привет всем! Захотел попробовать создать игру наподобие Clash of Clans. Как известно , в игре изометрическая графика. И я начал...

15
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
24.04.2016, 14:11
WelcomeToJam, Приведите пример изображения.
0
0 / 0 / 0
Регистрация: 23.04.2016
Сообщений: 11
24.04.2016, 14:19  [ТС]
Storm23, вот.
Миниатюры
Emgu cv. Изометрия окружности   Emgu cv. Изометрия окружности  
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
24.04.2016, 16:15
Цитата Сообщение от WelcomeToJam Посмотреть сообщение
Необходимо преобразовать фотографию из исходного вида во фронтальный
Шахматка - лишняя, она только мешает. Достаточно белого листа бумаги.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using System;
using System.Drawing;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
 
namespace OpenCVTemplate
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
 
        private void miOpen_Click(object sender, EventArgs e)
        {
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                var img = new Image<Bgr, byte>(ofd.FileName);
                var res = Process(img);
                pnResult.BackgroundImage = res.ToBitmap();
            }
        }
 
        private Image<Bgr, byte> Process(Image<Bgr, byte> image)
        {
            //params
            var binLimit = 190;
            var minRectRelativeArea = 0.06;
            var maxRectRelativeArea = 0.3;
            var paperWidth = 100;
            var paperHeight = 70;
            var accuracy = 1;
            var maxLevel = 5;
            var startPaperX = 100;
            var startPaperY = 100;
            var resultSize = new Size( image.Width*2, image.Height * 2);
 
            //convert to grayscale, prepare, binarization
            var gray = image.Convert<Gray, byte>();
            gray._EqualizeHist();
            gray._ThresholdBinary(new Gray(binLimit), new Gray(255));
 
            //calc min and max area of paper
            var minArea = image.Width * image.Height * minRectRelativeArea;
            var maxArea = image.Width * image.Height * maxRectRelativeArea;
 
            //find countours
            var contours = gray.FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE, RETR_TYPE.CV_RETR_LIST);
 
            //enumerate countours
            var result = new Image<Bgr, byte>(1, 1);
            using (var mem = new MemStorage())
            while (contours != null)
            {
                mem.Clear();
                var c = contours.ApproxPoly(accuracy, maxLevel, mem);//approximation
                var points = new PointF[c.Total];
                var j = 0;
                foreach (var p in c) points[j++] = p;
 
                if (c.Total == 4)//rectangle?
                if (c.Area > minArea && c.Area < maxArea)//filter
                {
                    //we have found paper rectangle
                    //make affine transform
                    result = MakeAffineTransform(image, points, startPaperX, startPaperY, startPaperX + paperWidth, startPaperY + paperHeight, resultSize);
                    break;
                }
                contours = contours.HNext;
            }
 
            gray.Dispose();
 
            return result;
        }
 
        private Image<Bgr, byte> MakeAffineTransform(Image<Bgr, byte> img, PointF[] markers3, float x0, float y0, float x1, float y1, Size resultSize)
        {
            var dist = new PointF[4];
 
            dist[0] = new PointF(x1, y0);
            dist[1] = new PointF(x0, y0);
            dist[2] = new PointF(x0, y1);
            dist[3] = new PointF(x1, y1);
 
 
            var matrix = CameraCalibration.GetPerspectiveTransform(markers3, dist);
            var res = img.WarpPerspective(matrix, resultSize.Width, resultSize.Height, INTER.CV_INTER_CUBIC, WARP.CV_WARP_DEFAULT, new Bgr(Color.Black));
 
            matrix.Dispose();
 
            return res;
        }
    }
}
1)Исходное изображение.
2)Бинаризируем.
3)Выделяем контуры, аппроксимируем прямыми, фильтруем.
4)Обратное перспективное преобразование.



Проект целиком (EmguCV 2.2, x86)
6
0 / 0 / 0
Регистрация: 23.04.2016
Сообщений: 11
06.05.2016, 12:01  [ТС]
А насколько точным будет, предложенное вами, преобразование? Просто, если использовать шахматку, то известен размер клетки. Далее, как мне кажется, мы можем с помощью аффинного или перспективного (пока не разобрался) преобразования, на основе этой самой длины, более точно преобразовать изображение во фронтальный вид.

Добавлено через 16 минут
В emgu даже методы специальные имеются, если не ошибаюсь.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
06.05.2016, 18:45
Цитата Сообщение от WelcomeToJam Посмотреть сообщение
Просто, если использовать шахматку, то известен размер клетки.
А если использовать лист, то известен размер листа.
Цитата Сообщение от WelcomeToJam Посмотреть сообщение
А насколько точным будет, предложенное вами, преобразование?
Ну не устраивает - делайте по другому, я не заставляю.
0
0 / 0 / 0
Регистрация: 23.04.2016
Сообщений: 11
13.05.2016, 14:34  [ТС]
C#
1
2
3
4
5
6
7
8
9
if (c.Total == 4) // rectangle?
   if (c.Area > minArea && c.Area < maxArea)// filter
   {
        //we have found paper rectangle
        //make affine transform
        result = MakeAffineTransform(image, points, startPaperX, startPaperY, 
                                                 startPaperX + paperWidth, startPaperY + paperHeight, resultSize);
        break;
    }
Можете объяснить в чем смысл фильтра и как влияют значения minArea/maxArea на него? Я загрузил картинку (ту, что прикрепил для примера), но почему-то она не прошла фильтр.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
13.05.2016, 15:05
Цитата Сообщение от WelcomeToJam Посмотреть сообщение
Можете объяснить в чем смысл фильтра и как влияют значения minArea/maxArea на него?
Фильтр отбирает прямоугольники по площади. Прямоугольник должен быть не очень маленький (это скорее всего будет не лист бумаги, а клетка шахматки или элемент фона или шум), но и не очень большой (в таком случае это могут быть крупноформатные объекты - сама комната, рамка кадра и т.п.). Соответственно параметры minArea и maxArea задают ожидаемую площадь листа бумаги.
0
0 / 0 / 0
Регистрация: 23.04.2016
Сообщений: 11
15.05.2016, 15:47  [ТС]
Странно, но при c.Total == 4 значения c.Area не превышают 25. Это при том, что minArea приблизительно = 14 000.

Добавлено через 3 часа 1 минуту
При Total = 133 Area получилась = 30 000, но разница с фильтруемым параметром (Total) очень большая. Не подскажите в чем проблема?
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
15.05.2016, 16:48
Цитата Сообщение от WelcomeToJam Посмотреть сообщение
Не подскажите в чем проблема?
Как я могу подсказать не видя изображения? Приведите изображение - скажу.

Скорее всего лист бумаги не выделился как прямоугоьник на бинаризированном изображении. Нужно настроить параметры бинаризации.
Для контроля бинаризированного изображения - сохраняйте изображение gray в файл и визуально посмотрите как бинаризируется.
0
0 / 0 / 0
Регистрация: 23.04.2016
Сообщений: 11
15.05.2016, 16:52  [ТС]
То же самое изображение, что я прикреплял как исходное.
0
0 / 0 / 0
Регистрация: 23.04.2016
Сообщений: 11
15.05.2016, 16:56  [ТС]
Вот оно.
Миниатюры
Emgu cv. Изометрия окружности  
0
0 / 0 / 0
Регистрация: 23.04.2016
Сообщений: 11
15.05.2016, 17:36  [ТС]
Вот они.
Вложения
Тип файла: zip IMG.zip (327.9 Кб, 10 просмотров)
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
15.05.2016, 21:05
WelcomeToJam,
В коде есть параметр accuracy, увеличьте его. Поставьте его равным например 5.

Немного теории.
Accuracy - это максимальная погрешность аппроксимации (в пикселах). Когда вы выкладывали предыдущее изображение, у него было разрешение 427x551 и accuracy= 1 было достаточно, что бы аппроксимировать лист бумаги прямоугольником.
Но вы тестируете на изображении в большем разрешении: 1116x1512. Поэтому ваша аппроксимация получается слишком подробной. Вот такой:



Здесь показан увеличенный фрагмент края листа. Красные линии - это линии аппроксимации. Зеленые точки - это концы этих линий. Вам нужно получить ровно 4 линии и 4 точки, которые будут апроксимировать ваш лист бумаги как прямоугольник. Но на рисунке видно, что апроксимация слишком подробная и аппроксимация содержит множество мелких линий. Поэтому ее нужно сделать более грубой. Для этого и повышается параметр accuracy.

Вот тот же фрагмент изображения для accuracy = 5:



Как видите, теперь края листа аппроксимируются ровной линией, с ровно одной точкой в углу. Как нам и нужно.

В целом, если вы заранее не знаете какого размера будет изображение, и вам нужно что бы алгоритм работал при любых разрешениях, то вам нужно:
1) Либо высчитывать значение accuracy, исходя из размеров изображения. Например по формуле: accuracy = img.Width / 20;
2) Либо же наоборот, параметры оставлять константыми, но само изображение предварительно ресайзить к нужному размеру (например к ширине 800).

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

И еще, вот вам немного измененный вариант исходника:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
using System;
using System.Drawing;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
 
namespace OpenCVTemplate
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
 
        private void miOpen_Click(object sender, EventArgs e)
        {
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                var img = new Image<Bgr, byte>(ofd.FileName);
                var res = Process(img);
                pnResult.BackgroundImage = res.ToBitmap();
            }
        }
 
        private Image<Bgr, byte> Process(Image<Bgr, byte> image)
        {
            //params
            var binLimit = 190;
            var minRectRelativeArea = 0.06;
            var maxRectRelativeArea = 0.3;
            var paperWidth = 100;
            var paperHeight = 70;
            var accuracy = 5;
            var maxLevel = 5;
            var startPaperX = 100;
            var startPaperY = 100;
            var resultSize = new Size( image.Width*2, image.Height * 2);
 
            //convert to grayscale, prepare, binarization
            var gray = image.Convert<Gray, byte>();
            gray._EqualizeHist();
            gray._ThresholdBinary(new Gray(binLimit), new Gray(255));
 
#if DEBUG
            gray.Save("c:\\temp.png");
#endif
 
            //calc min and max area of paper
            var minArea = image.Width * image.Height * minRectRelativeArea;
            var maxArea = image.Width * image.Height * maxRectRelativeArea;
 
            //find countours
            var contours = gray.FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE, RETR_TYPE.CV_RETR_LIST);
 
            //enumerate countours
            var result = new Image<Bgr, byte>(1, 1);
            using (var mem = new MemStorage())
            while (contours != null)
            {
                mem.Clear();
                var c = contours.ApproxPoly(accuracy, maxLevel, mem);//approximation
                var points = new PointF[c.Total];
                var j = 0;
                foreach (var p in c) points[j++] = p;
 
#if DEBUG
                image.Draw(c, new Bgr(Color.Red), 1);
                foreach (var p in points)
                    image.Draw(new Ellipse(p, new SizeF(1, 1), 0), new Bgr(Color.Lime), 1);
#endif
 
                if (c.Total == 4)//rectangle?
                if (c.Area > minArea && c.Area < maxArea)//filter
                {
                    //we have found paper rectangle
                    //make affine transform
                    result = MakeAffineTransform(image, points, startPaperX, startPaperY, startPaperX + paperWidth, startPaperY + paperHeight, resultSize);
                    break;
                }
                contours = contours.HNext;
            }
 
#if DEBUG
            image.Save("c:\\temp1.png");
#endif
 
            gray.Dispose();
 
            return result;
        }
 
        private Image<Bgr, byte> MakeAffineTransform(Image<Bgr, byte> img, PointF[] markers3, float x0, float y0, float x1, float y1, Size resultSize)
        {
            var dist = new PointF[4];
 
            dist[0] = new PointF(x1, y0);
            dist[1] = new PointF(x0, y0);
            dist[2] = new PointF(x0, y1);
            dist[3] = new PointF(x1, y1);
 
 
            var matrix = CameraCalibration.GetPerspectiveTransform(markers3, dist);
            var res = img.WarpPerspective(matrix, resultSize.Width, resultSize.Height, INTER.CV_INTER_CUBIC, WARP.CV_WARP_DEFAULT, new Bgr(Color.Black));
 
            matrix.Dispose();
 
            return res;
        }
    }
}

Для того, что бы вам было легче отлаживать, эта версия сохраняет на диск два изображения - бинаризированное и с отрисованными аппроксимационными линиями (в Debug конфигурации).
0
0 / 0 / 0
Регистрация: 23.04.2016
Сообщений: 11
18.05.2016, 18:11  [ТС]
accuracy = img.Width / 20? Возможно, вы имели ввиду 200? А то цифра больно большая получается.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
18.05.2016, 18:42
Цитата Сообщение от WelcomeToJam Посмотреть сообщение
accuracy = img.Width / 20? Возможно, вы имели ввиду 200? А то цифра больно большая получается.
Да, 200.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.05.2016, 18:42
Помогаю со студенческими работами здесь

3-ий вид детали и изометрия
Помогите, пожалуйста, изобразить изометрию и третий вид объекта. Пробовала для построения 3D фигуры ограничиться теми видами, которые уже...

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

2d графика и изометрия в java
Доброго времени суток. Какие есть средства в java, для создания изометрической картинки (изометрического холста). И с помощью чего можно...

Разработка игр. Изометрия на плоскости
Подскажите/укажите как правильно соблюсти порядок вывода текстур, перелопатил все эти z-индексы, ничего не выходит, а гугл как на зло...

Определить какая из точек лежит на окружности, какая внутри окружности, а какая вне окружности
Не могу не как понять какую формулу писать Вот задания Заданы координаты двух точек А(х,у) и В(х,у) и радиус окружности r. Определить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru