Страница: 1 | 2 |
Вопрос: Попиксельное сравнение картинок
Добавлено: 07.06.10 13:36
Автор вопроса: Spiritsun
Облазил инет, ничо толкового не нашел. Помогите, пж., как очень быстро сравнить битмап в памяти? Средствами getpixel через цыклы - это долго. Пробовал Object.Equals, он сравнивает теги, а не нутро. Может есть какие внутренние команды, которые, например, сравнивали бы битовые представления объектов в памяти не трогая теги?
Куски имеют одинаковый размер. Интересует только нутро.
Ответы
Всего ответов: 28
Номер ответа: 1
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #1
Добавлено: 07.06.10 14:45
public System.IntPtr Scan0 { set; get; }
Member of System.Drawing.Imaging.BitmapData
Summary:
Gets or sets the address of the first pixel data in the bitmap. This can also be thought of as the first scan line in the bitmap.
Returns:
The address of the first pixel data in the bitmap.
Тебе надо копать в эту сторону.. Используя эту фичу, ты получишь указатель на первый байт картинки в памяти, зная размеры картинки и ее глубину цвета ты сможешь создать байтовый массив нужного размера и скопировать в него картинку из памяти одним махом.. Таким образом ты получишь байтовый массив в котором представлена картинка.. Все что тебе останется - это лишь пробежаться одним циклом по массивам и сравнить байты. Если хоть одна пара байт различается то значит картинки не равны..
Если пишешь на С# и умеешь юзать unsafe код с указателями, то даже копировать ничего никуда не надо.. Надо будет лишь залочить картинки в памяти и провести сравнение прям на месте..
Номер ответа: 2
Автор ответа:
Spiritsun
Вопросов: 15
Ответов: 44
Профиль | | #2
Добавлено: 07.06.10 16:08
Ага, хороший совет, пасиб. А есть ли команда сравнения блоков памяти? Ну чтоб не юзать циклы. Или как вариант не блоков памяти, а массивы, если обе картинки загнать туда.
Номер ответа: 3
Автор ответа:
Artyom
Разработчик
Вопросов: 130
Ответов: 6602
Профиль | | #3
Добавлено: 07.06.10 16:35
Есть Enumerable.SequenceEqual
Поскольку работает через IEnumerable, то работать будет медленно, в место этого лучше сделать обычным циклом - будет быстрее.
Также можно еще быстрее сделать, если использовать unsafe указатели - не будет проверки выхода за границы массива.
Номер ответа: 4
Автор ответа:
Сергей
ICQ: 558230345
Вопросов: 7
Ответов: 91
Профиль | | #4
Добавлено: 07.06.10 16:36
попробуй посчитать контрольную сумму каждого рисунка и сравнить их
Номер ответа: 5
Автор ответа:
Artyom
Разработчик
Вопросов: 130
Ответов: 6602
Профиль | | #5
Добавлено: 08.06.10 14:04
контрольная сумма здесь не нужна
Номер ответа: 6
Автор ответа:
Сергей
ICQ: 558230345
Вопросов: 7
Ответов: 91
Профиль | | #6
Добавлено: 08.06.10 16:53
Почему? Вопрос ведь в сравнении двух битмапов а не в выявлении различий. Посчитать контрольную сумму быстрее чем перебрать массив пикселей. Исравнить две суммы проще и быстрее.
Номер ответа: 7
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #7
Добавлено: 08.06.10 18:10
Чтобы посчитать контрольную сумму, нужно пройтись по всему массиву. Если в файле всего одно отличие, по матожиданию достаточно пройти половину массива.
Номер ответа: 8
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #8
Добавлено: 08.06.10 18:28
А ну ка, просвяти.. как ты собираешься считать контрольную сумму картинки при условии что у них одинаковый размер?
Номер ответа: 9
Автор ответа:
Администратор
ICQ: 278109632
Вопросов: 42
Ответов: 3949
Web-сайт:
Профиль | | #9
Добавлено: 08.06.10 19:06
А какая разница, какой у них размер? КоHрольная сумма будет разной при разности хоть одного бита.
Номер ответа: 10
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #10
Добавлено: 08.06.10 19:21
в том то и фишка, что автор каким то образом хочет посчитать сумму без испоьзования циклов.. вот мне и интересно как..
Номер ответа: 11
Автор ответа:
VβÐUηìt
Вопросов: 246
Ответов: 3333
Web-сайт:
Профиль | | #11
Добавлено: 08.06.10 20:31
oO Просвятите, если я в чем то не прав:
В попу контрольную сумму (буэ). Туда же циклы (буээээээ!). Берем картинку А и картинку Б. Сначала сравниваем их размеры - если не совпадают - False. Затем, если они совпадают, накладываем А на другое с помощью BitBlt(.NET - DrawImageUnstretched) с битовой операцией такой, чтобы получалась разница (хоть какая-то, не помню там уже что именно, помню, что есть что-то такое ). Так вот, таким образом, получаем изображение, на котором отмечены только несовпадающие пиксели. То есть, если такой-то пиксель васи А равен соответствующему пикселю васи Б, то выбранная нами (не случайно) битовая операция сделает что-нибудь, обращающее цвет этого пикселя в константу. Дальше делаем SetStretchBltMode (.NET - Smoothing = Smoothing.HighQuality, или как там), и StretchBlt (.NET - DrawImage) на битмап с новыми значениями ширины 1 и высоты 1, то есть ужимаем нашего васю в один пиксель. Далее смотрим: если, допустим, наша битовая операция делал все одинаковые пиксели черными (как наложение "разница" в фотошопе), а неодинаковые - нечерными (какими-нибудь), то степень отличия картинок изменяется отличием цвета новоиспеченного пикселя от черного цвета. Ну как? Понятно, что способ не очень точен (на изображениях от 16x16 пикселей ), но зато, я полагаю, работает на порядки быстрее двух циклов. Остается только уточнить, есть ли хороший, годный битовый фильтр наложения для этой расты (не удержался). Смекнули?
Номер ответа: 12
Автор ответа:
Сергей
ICQ: 558230345
Вопросов: 7
Ответов: 91
Профиль | | #12
Добавлено: 09.06.10 09:53
есть подозрение, что вычисление контрольной суммы двух файлов стандартными средствами будет быстрее, чем "ручной" перебор двух массивов и пошаговое сравнение элементов массива. Во всяком случае из опыта это так. Хотя зависит от того, какой алгоритм подсчета используется.
Номер ответа: 13
Автор ответа:
Artyom
Разработчик
Вопросов: 130
Ответов: 6602
Профиль | | #13
Добавлено: 09.06.10 10:37
Посчитать контрольную сумму быстрее чем перебрать массив пикселей
неверно
Исравнить две суммы проще и быстрее
верно, при условии что контрольные суммы уже были заранее подсчитаны
Чтобы посчитать контрольную сумму, нужно пройтись по всему массиву. Если в файле всего одно отличие, по матожиданию достаточно пройти половину массива.
Верно
oO Просвятите, если я в чем то не прав:
В попу контрольную сумму (буэ). Туда же циклы (буээээээ!). Берем картинку А и картинку Б. Сначала сравниваем их размеры - если не совпадают - False. Затем, если они совпадают, накладываем А на другое с помощью BitBlt(.NET - DrawImageUnstretched) с битовой операцией такой, чтобы получалась разница (хоть какая-то, не помню там уже что именно, помню, что есть что-то такое ). Так вот, таким образом, получаем изображение, на котором отмечены только несовпадающие пиксели. То есть, если такой-то пиксель васи А равен соответствующему пикселю васи Б, то выбранная нами (не случайно) битовая операция сделает что-нибудь, обращающее цвет этого пикселя в константу. Дальше делаем SetStretchBltMode (.NET - Smoothing = Smoothing.HighQuality, или как там), и StretchBlt (.NET - DrawImage) на битмап с новыми значениями ширины 1 и высоты 1, то есть ужимаем нашего васю в один пиксель. Далее смотрим: если, допустим, наша битовая операция делал все одинаковые пиксели черными (как наложение "разница" в фотошопе), а неодинаковые - нечерными (какими-нибудь), то степень отличия картинок изменяется отличием цвета новоиспеченного пикселя от черного цвета. Ну как? Понятно, что способ не очень точен (на изображениях от 16x16 пикселей ), но зато, я полагаю, работает на порядки быстрее двух циклов. Остается только уточнить, есть ли хороший, годный битовый фильтр наложения для этой расты (не удержался). Смекнули?
Эта битовая операция называется XOR. В остальном - подходит как наглядное пособие по удалению гланд через жопу.
есть подозрение, что вычисление контрольной суммы двух файлов стандартными средствами будет быстрее, чем "ручной" перебор двух массивов и пошаговое сравнение элементов массива.
Я бы на твоем месте не полагался на свою интуицию, по крайней мере пока опыт программирования не превысит 10 лет.
Номер ответа: 14
Автор ответа:
Сергей
ICQ: 558230345
Вопросов: 7
Ответов: 91
Профиль | | #14
Добавлено: 09.06.10 12:44
Скромность не позволяет, но я пересилю себя. Программировать я начал еще в 1992 году. С ассемблера. 18 лет достаточно?
Номер ответа: 15
Автор ответа:
Artyom
Разработчик
Вопросов: 130
Ответов: 6602
Профиль | | #15
Добавлено: 09.06.10 13:28
18 лет должно быть достаточно. Но странно, что человек, который программирует 18 лет (професионально? без перерывов?) так слабо разбирается в элементарных вещах.