70 / 69 / 10
Регистрация: 14.06.2009
Сообщений: 310
Записей в блоге: 1
1

Найти координаты вхождения изображения(1) в изображение(2)

05.08.2010, 17:06. Показов 4365. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте,
задача следующая:
Найти координаты вхождения изображения(1) в изображение(2).
Пример:
(2)изображение 800х600 черного цвета.
где-то на изображении белый круг 4х4 пикселя.
(1)изображение 4х4 белый круг на черном фоне.

Подскажите алгоритм?

предположение такое:
1.Перевести оба Bitmap'a в массивы байтов.
2.Искать вхождение одного массива в другой.

Был бы рад если подскажите по обоим пунктам.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.08.2010, 17:06
Ответы с готовыми решениями:

Найти координаты первого вхождения в заданную строку подстроки, состоящей из двух одинаковых заданных символов
Найти координаты первого вхождения в заданную строку подстроки, состоящей из двух одинаковых...

При наведении на изображение,изображение должн немного затемнится и + по центру изображения треугольник
Вот допустим у меня 3 картинки: нужно чтоб при наведении на любую из них,затемнялось и картинка...

Процедура: при клике на изображение найти расстояние между центром этого и центром другого изображения
Доброго времени суток! При клике на изображение1 высчитывается длина между центром этого...

Координаты при нажатии на изображение
Возникла проблема, как при нажатии на Image получить координаты места куда нажали? Вообще идей...

16
Заблокирован
05.08.2010, 17:15 2
4*4, значит радиус=2
х1=х-2, х2=х+2, у1=y-2, y2=y+2 (x,у)-координаты центра круга
или у тебя битмап с кругом круглый
0
70 / 69 / 10
Регистрация: 14.06.2009
Сообщений: 310
Записей в блоге: 1
05.08.2010, 17:30  [ТС] 3
эм. зачем мне центр круга? мне нужны координаты этого круга в изображении 800х600
а круг из себя представляет как раз эту картинку 4х4

Добавлено через 13 секунд
эм. зачем мне центр круга? мне нужны координаты этого круга в изображении 800х600
а круг из себя представляет как раз эту картинку 4х4
0
Заблокирован
05.08.2010, 17:40 4
тогда найди в цикле через GetPixel битмапа (или поверхности на которой рисуешь)координаты первой белой точки(х,у)
(внешний цикл по у, внутренний по х)
(х-1,у) - координаты левого верхнего угла маленького битмапа
1
70 / 69 / 10
Регистрация: 14.06.2009
Сообщений: 310
Записей в блоге: 1
05.08.2010, 20:15  [ТС] 5
это грубый пример, представь что фон не черный а разноцветный=) нужно именно комбинацию пикселей найти. к примеру 4х4, но может и больше

нужно решение в общем
0
283 / 262 / 32
Регистрация: 11.11.2009
Сообщений: 605
05.08.2010, 20:33 6
Цитата Сообщение от EatingPeopleIsFun Посмотреть сообщение
Здравствуйте,
задача следующая:
Найти координаты вхождения изображения(1) в изображение(2).
Пример:
(2)изображение 800х600 черного цвета.
где-то на изображении белый круг 4х4 пикселя.
(1)изображение 4х4 белый круг на черном фоне.

Подскажите алгоритм?

предположение такое:
1.Перевести оба Bitmap'a в массивы байтов.
2.Искать вхождение одного массива в другой.

Был бы рад если подскажите по обоим пунктам.
Я бы сделал так:
1.Перевести оба Bitmap'a в двухмерные массивы байтов.
2.Искать вхождение одной матрицы в другой.
0
70 / 69 / 10
Регистрация: 14.06.2009
Сообщений: 310
Записей в блоге: 1
05.08.2010, 20:43  [ТС] 7
1)как именно перевести bitmap в двумерный массив байтов? переводить цвета пикселей? или как?
2)было время пытался найти информацию по этому поводу, нашел только про вхождения строк.

в принципе эту проблему я решал раньше, но "через задний проход", переводил изображения в строки, через коды цветов, и искал вхождения строк)

вот хочу узнать нормальный способ...
0
283 / 262 / 32
Регистрация: 11.11.2009
Сообщений: 605
05.08.2010, 20:53 8
Цитата Сообщение от EatingPeopleIsFun Посмотреть сообщение
1)как именно перевести bitmap в двумерный массив байтов? переводить цвета пикселей? или как?
2)было время пытался найти информацию по этому поводу, нашел только про вхождения строк.

в принципе эту проблему я решал раньше, но "через задний проход", переводил изображения в строки, через коды цветов, и искал вхождения строк)

вот хочу узнать нормальный способ...
не претендуя на "нормальный способ" может (и скорее всего) есть более оптимальные способы, но нашел код, который похож на то что как я думал делать:
C#
1
2
3
4
5
6
7
8
9
10
11
                // Retrieve the image.
                Bitmap image1 = new Bitmap(@"C:/bitmap.bmp", true);
                Color[,] array = new Color[image1.Width, image1.Height];               
                for (int x = 0; x < image1.Width; x++)
                {
                    for (int y = 0; y < image1.Height; y++)
                    {
                        array[x,y] = image1.GetPixel(x, y);
                                              
                    }
                }
а дальше по идее ищешь вхождение первой строки в строках большего битмапа,
нашел, со следующей строки проверяешь есть ли совпадение по остальным строкам,
нет, продолжили поиск
1
70 / 69 / 10
Регистрация: 14.06.2009
Сообщений: 310
Записей в блоге: 1
05.08.2010, 21:03  [ТС] 9
ну вот оно всё сработает, но это как-то не так=)) нету других способов?)
0
Заблокирован
05.08.2010, 22:07 10
Цитата Сообщение от Dzhej-Dzhej Посмотреть сообщение
тогда найди в цикле через GetPixel битмапа
Ага, и жди стопятьсот тысяч лет, пока тормозной GetPixel отработает на всей картинке. Для указанных 800x600 и 4x4 это будет в максимуме 800x600x4x4 раз. К тому времени Вселенная состарится.

Цитата Сообщение от new_in_net Посмотреть сообщение
1.Перевести оба Bitmap'a в двухмерные массивы байтов.
Прости, а Bitmap за массив не сойдёт?

Цитата Сообщение от new_in_net Посмотреть сообщение
а дальше по идее ищешь вхождение первой строки в строках большего битмапа,
нашел, со следующей строки проверяешь есть ли совпадение по остальным строкам,
нет, продолжили поиск
Теоретик кайфа

- Как заработать миллион?
- Ну берёшь, зарабатываешь сотню, а дальше в том же духе....

Цитата Сообщение от EatingPeopleIsFun Посмотреть сообщение
ну вот оно всё сработает, но это как-то не так=)) нету других способов?)
Смотри, показываю правильный кошерный быстрый способ.

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
public Point? FindSubimage(Bitmap image, Bitmap subimage)
{
    if (image.PixelFormat != PixelFormat.Format24bppRgb ||
        subimage.PixelFormat != PixelFormat.Format24bppRgb)
            throw new ApplicationException("Invalid pixel format");
 
    unsafe
    {
        BitmapData data1 = image.LockBits(
            new Rectangle(0, 0, image.Width, image.Height),
            ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
        var pBase1 = (byte*) data1.Scan0;
 
        BitmapData data2 = subimage.LockBits(
            new Rectangle(0, 0, subimage.Width, subimage.Height),
            ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
        var pBase2 = (byte*) data2.Scan0;
 
        for (int j = 0; j < image.Height; j++)
        {
            for (int i = 0; i < image.Width; i++)
            {
                for (int jj = 0; jj < subimage.Height; jj++)
                    for (int ii = 0; ii < subimage.Width; ii++)
                    {
                        byte* pixel1 = pBase1 + (j + jj)*data1.Stride + (i + ii)*3;
                        byte* pixel2 = pBase2 + jj*data2.Stride + ii*3;
 
                        if (*pixel1 != *pixel2 ||
                            *(pixel1 + 1) != *(pixel2 + 1) ||
                            *(pixel1 + 2) != *(pixel2 + 2))
                        {
                            goto next;
                        }
                    }
 
                    return new Point(i, j);
                next:
                    continue;
                }
            }
 
            subimage.UnlockBits(data2);
            image.UnlockBits(data1);
    }
 
    return null;
}
Объясняю вкрадце.
image - исходная картинка, в которой будем искать подкартинку,
subimage - картинка, которую будем искать в image
Возвращает функция Point с найденными координатами, а если не нашла вхождение - null.

Работает быстро (намного быстрее, чем через GetPixel) за счёт того, что зная формат изображения, мы можем откинуть кучу разных проверок. Изображения должны быть RGB и иметь по восемь бит на канал. Если захочешь добавить, например, альфа канал, замени Format24bppRgb на, например, Format32bppArgb и множители 3 на 4.... ну и т.д. в зависимости от формата изображений.

В настройках проекта не забудь выставить Allow unsafe code.

Использовать так:
C#
1
2
3
4
5
6
7
8
9
var bmp1 = (Bitmap)Image.FromFile(@"1.bmp");
var bmp2 = (Bitmap)Image.FromFile(@"2.bmp");
 
Point? pt = FindSubimage(bmp1, bmp2);
 
if (pt.HasValue)
    MessageBox.Show(pt.ToString());
else
    MessageBox.Show(@"Not found");
1
70 / 69 / 10
Регистрация: 14.06.2009
Сообщений: 310
Записей в блоге: 1
05.08.2010, 22:36  [ТС] 11
завтра буду тестить)
с виду реально кашерный способ))
а можно вопросы позадавать? что за знак вопроса
C#
1
Point?
первый раз с таким сталкиваюсь.

и почему тут код unsafe?

P.s: Спасибо большое!!
0
Заблокирован
05.08.2010, 22:49 12
Цитата Сообщение от EatingPeopleIsFun Посмотреть сообщение
что за знак вопроса
C#
1
Point?
первый раз с таким сталкиваюсь.
Короткая запись вот такой вещи:
C#
1
Nullable<Point>
может принимать значения, как типа Point, так и null + имеет полезные свойства вроде HasValue.

Цитата Сообщение от EatingPeopleIsFun Посмотреть сообщение
и почему тут код unsafe?
Потому что работаем напрямую с памятью через указатели.
1
70 / 69 / 10
Регистрация: 14.06.2009
Сообщений: 310
Записей в блоге: 1
06.08.2010, 21:22  [ТС] 13
у меня изображения с PixelFormat.Format32bppArgb
изменил формат и множители на 4 - не находит.
изменил формат а множители оставил 3 - всё работает отлично.

успешно подредактировал чтобы искал, отталкиваясь от начальных координат, т.к. у меня subimage встречается несколько раз)
0
Заблокирован
06.08.2010, 22:38 14
Цитата Сообщение от EatingPeopleIsFun Посмотреть сообщение
у меня изображения с PixelFormat.Format32bppArgb
Тогда вот так. (Да, забыл сказать, нужно ещё проверку для альфа-канала сделать тогда: *(pixel1 + 3) != *(pixel2 + 3) ).

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
public Point? FindSubimage(Bitmap image, Bitmap subimage)
{
    if (image.PixelFormat != PixelFormat.Format32bppArgb ||
        subimage.PixelFormat != PixelFormat.Format32bppArgb)
            throw new ApplicationException("Invalid pixel format");
 
    unsafe
    {
        BitmapData data1 = image.LockBits(
            new Rectangle(0, 0, image.Width, image.Height),
            ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        var pBase1 = (byte*) data1.Scan0;
 
        BitmapData data2 = subimage.LockBits(
            new Rectangle(0, 0, subimage.Width, subimage.Height),
            ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        var pBase2 = (byte*) data2.Scan0;
 
        for (int j = 0; j < image.Height; j++)
        {
            for (int i = 0; i < image.Width; i++)
            {
                for (int jj = 0; jj < subimage.Height; jj++)
                    for (int ii = 0; ii < subimage.Width; ii++)
                    {
                        byte* pixel1 = pBase1 + (j + jj)*data1.Stride + ((i + ii) << 2);
                        byte* pixel2 = pBase2 + jj*data2.Stride + (ii << 2);
 
                        if (*pixel1 != *pixel2 ||
                            *(pixel1 + 1) != *(pixel2 + 1) ||
                            *(pixel1 + 2) != *(pixel2 + 2) ||
                            *(pixel1 + 3) != *(pixel2 + 3))
                        {
                            goto next;
                        }
                    }
 
                return new Point(i, j);
                next:
                    continue;
            }
        }
 
        subimage.UnlockBits(data2);
        image.UnlockBits(data1);
    }
 
    return null;
}
0
70 / 69 / 10
Регистрация: 14.06.2009
Сообщений: 310
Записей в блоге: 1
06.08.2010, 23:23  [ТС] 15
мне Альфа канал в принципе не нужен, и если ставить <<2 отказывается искать) остановлюсь на варианте с множителем 3)
спасибо)
0
Заблокирован
07.08.2010, 03:21 16
Цитата Сообщение от EatingPeopleIsFun Посмотреть сообщение
мне Альфа канал в принципе не нужен, и если ставить <<2 отказывается искать) остановлюсь на варианте с множителем 3)
спасибо)
Мне кажется, это неправильно. Не должно быть 3 для argb. Лучше поищи причину. У меня, кстати, для argb *4 (или <<2, что то же самое) работает.
0
0 / 0 / 0
Регистрация: 04.02.2012
Сообщений: 13
04.04.2012, 15:53 17
Подыму тему...

Цитата Сообщение от NightmareZ Посмотреть сообщение
Смотри, показываю правильный кошерный быстрый способ.
Спасибо! Работает.

Правда время выполнения 1054мс на i5 8ГБ мозгов, 800х600 имидж и 8х8 сабимидж.
Интересно, есть алгоритмы бегающие раз в десять быстрее?
0
04.04.2012, 15:53
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.04.2012, 15:53
Помогаю со студенческими работами здесь

Даны целочисленные координаты трех вершин прямоугольника, найти координаты четвертой
Даны целочисленные координаты трех вершин прямоугольника, стороны которого параллельны координатным...

Найти координаты противоположных углов квадрата если известны координаты A и B
На плоскости дан квадрат ,известны координаты двух его углов ,найти координаты оставшихся двух . ...

Координаты для изображения
Здраствуйте! Скрипт highslide содержит пример image-map (где при нажати на страну, которая...

Найти координаты B, зная координаты A, расстояние до B, зенит и азимут
В трёхмерном пространстве \alpha (x;y;z) есть объект с центром A({x}_{0};{y}_{0};{z}_{0}), зенитный...


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru