также можно провести 2(исключаем проход одной из них между двумя штрихами) пересекающиеся диагонали диагонали
> Как вы определите что пиксель принадлежит штриху, а не цифре к примеру без описания контура ? по размеру?
Tronix ну, с такой реакцией и помогать не охота. думаю, вы воспользуетесь мозгами и сами все решите. распознавать же умеете.
Градусов 30 люфта у меня распознается. Главное чтобы хотябы одна линия прошлась по всем значащим точкам. Но хочется большего.
Tronix Попробуй повертеть штрихкод и подсчитать количество переходов белый-чёрный между соседними точками по горизонтали и вертикали, думаю что по соотношению этих двух чисел определить угол на который нужно поворачивать с точностью в пару десятков градусов будет несложно.
Решение номер 0 (самое простое и без графов и князей). Предполагаем что функция распознавания достаточно вменяема и ее можно звать с сильно повернутой картинкой и она не похоронит всю систему повалившись в экцпшен (даже если так - апкладываем ее сехом и так долее). Зовем ее для начального состояния (примем что это некий угол A0). Далее поворачиваем кортинку и все время смотрим че функция вернула. Отклик может быть при неких углах (A0+-dA), гдк dA - небольшое отклонение от истинного угла A0. Таким образом функция вернет ряд правильных значений штрихкода на некотром интервале [A1,A2]. Этот интервал можно найти перебором углов или умнее. Если надо, могу продолжить. Решение номер 2 (самое лучшее среди всех решений) Считываем всю кортинку в матрицу {Xi,Yi} - набор точек на плоскости (черно-белый). Находим центр массо всех точков, это будет где-то в области середины штрих-кода. Далее действительно можно применять приближающий прямоугольнег или линии (но не ОДНУ ЛИНИЮ!!!) для поиска самого описывающего. Критерий - рекомендую Хи-квадрат он же Пирсон.
Решение номер 3 (самое красивое) Считываем кортинко в виде матрицы. Далее предполагаем что мы знаем как генерируеца штрих-код и генерируем свою кортинку на основании аргумента 0 (было закодировано число 0). Пытаемся брутфосом - поворачивая свою или оригинальную кортинку - сопоставить обе и по критерию (выше) получить наиболее подходящую. В результате мы перебором как бы нарисуем ту же самую что и настоящая картинка под неким близким к истЕнному углу поворота.
Код (Text): NextPixel(X, Y, Vector): dX, dY = [(+1, +1), (+1, -1), (-1, -1), (-1, +1)][Vector] X = X + dX Y = Y + dY if POINT(X, Y) Vector = (Vector + 1) && 3 else dX, dY = [(-1, 0), (0, +1), (+1, 0), (0, -1)][Vector] X = X + dX Y = Y + dY if !POINT(X, Y) Vector = (Vector - 1) && 3 end Describe(X, Y): Vector = 0 ; Up X0 = X Y0 = Y Xmin = X Xmax = X Ymin = Y Ymax = Y NextPixel(X, Y, Vector) Do if X < Xmin Xmin = X endif if X > Xmax Xmax = X endif if Y < Ymin Ymin = Y endif if Y > Ymax Ymax = Y endif NextPixel(X, Y, Vector) Loop Vector | (X != X0) | (Y != Y0) Angle = (Ymax - Ymin)/(Xmax - Xmin) end Проверка приращения не показана. Также поиск пикселя справа не показан.
имхо решение влоб сканируем попиксельно слева направо вдоль вертикали и ищем черный пиксель после которого на следующей строке идет черный, зная что цифры находятся определенно ниже нужного изображения, сканируем дальше пока не встретим белый пиксель после черного на основе запомненных двух пикселей из уравнения прямой находим tg(a), где а угол наклона картинки вертим ее как надо. либо находим перпендикуляр к этой линии и проходимся по нему смещенному вниз на пару пикселей выделяем координаты черных пикселей и на основании этих точек и факта перпендикулярности направляющего перпендикуляра получаем нужное изображение математика школы-первого курса
Можно просто подобрать положение изображения, при котором его высота, т.е. расстояние по вертикали между самым верхним и самым нижним чёрным пикселями, минимальна. Изображение может получиться перевёрнутым вверх ногами.
Пытаемся распознать - не получилось - поворачиваем на 180 градусов - пытается распознать - не получилось - штрих код не корректный.
!Всё не читал, может баян. 1.Понизить разрешение до <подобрать при наладке опримальное>. 2.Выполнить серию сканирований (красным на картинке), с шагом <подобрать при наладке опримальное> градусов(без поворота кртинки), в результе получим некоторый набор чисел. 3.Найти два лучших(наиблее похожих)(в том числе и меняя порядок следования знаков так как картинка может быть кверхногами), и выполнить несколько дополнительных сканирований(на картинке зелёным) между этими двумя лучшими(для подтверждения). 4.Если подтвердить результат не удалось - повысить разрешение и к 2, иначе OK. ADD: Если штрих код может быть не в центре изображения, то его можно разбить на несколько участков и выполнить 2 для каждого их них.
Набросал простейший код: Код (Text): IMAGE_WIDTH equ 707 IMAGE_HEIGHT equ 399 .data hBitmap HANDLE ? hDC HANDLE ? .code $Image CHAR "Scan.bmp",0 VECTOR_UP equ 0 VECTOR_RIGHT equ 1 VECTOR_DOWN equ 2 VECTOR_LEFT equ 3 Point proc X:ULONG, Y:ULONG mov eax,X mov ecx,Y test eax,eax jl Over test ecx,ecx jl Over cmp eax,IMAGE_WIDTH mov edx,IMAGE_HEIGHT ja Over cmp ecx,edx ja Over sub edx,ecx invoke GetPixel, hDC, Eax, Edx cmp al,200 setb al movzx eax,al @@: ret Over: xor eax,eax jmp @b Point endp NextVector proc uses ebx esi edi X:PULONG, Y:PULONG, Vector:PULONG mov ebx,Vector Scan: mov esi,X mov edi,Y mov eax,dword ptr [ebx] mov esi,dword ptr [esi] mov edi,dword ptr [edi] add esi,dword ptr [FirstTable + eax*8] add edi,dword ptr [FirstTable + eax*8 + 4] invoke Point, Esi, Edi test eax,eax jnz Fpt mov eax,dword ptr [ebx] add esi,dword ptr [NextTable + eax*8] add edi,dword ptr [NextTable + eax*8 + 4] invoke Point, Esi, Edi test eax,eax jnz Load dec dword ptr [ebx] and dword ptr [ebx],11B jmp Scan ; Ext. ; jmp Exit Fpt: inc dword ptr [ebx] Load: mov ecx,X mov edx,Y mov dword ptr [ecx],esi mov dword ptr [edx],edi Exit: and dword ptr [ebx],11B ret ; dX dY FirstTable: DD +1, +1 DD +1, -1 DD -1, -1 DD -1, +1 NextTable: DD -1, 0 DD 0, +1 DD +1, 0 DD 0, -1 NextVector endp FindPoint proc uses ebx esi edi X:PULONG, Y:PULONG, Vector:ULONG mov ebx,Vector mov esi,X mov edi,Y mov esi,dword ptr [esi] mov edi,dword ptr [edi] @@: add esi,dword ptr [VectorTable + ebx*8] add edi,dword ptr [VectorTable + ebx*8 + 4] invoke Point, Esi, Edi test eax,eax jz @b mov ecx,X mov edx,Y mov dword ptr [ecx],esi mov dword ptr [edx],edi ret VectorTable: DD 0, +1 DD +1, 0 DD 0, -1 DD -1, 0 FindPoint endp Describe proc Local X:ULONG, Y:ULONG Local Xp:ULONG, Yp:ULONG Local Vector:ULONG, StartVector:ULONG Local Xmin:ULONG, Xmax:ULONG, Ymin:ULONG, Ymax:ULONG mov ebx,IMAGE_HEIGHT ; Y для поиска поверхности справа. NextLine: xor esi,esi NextPixel: mov edi,ebx invoke Point, Esi, Edi test eax,eax jnz @f inc esi cmp esi,IMAGE_WIDTH jb NextPixel dec ebx jnz NextLine Int 3 @@: mov X,esi mov Y,edi mov Vector,VECTOR_DOWN invoke NextVector, addr X, addr Y, addr Vector mov esi,X mov edi,Y mov eax,Vector mov Xmin,esi mov Xmax,esi mov Ymin,edi mov Ymax,edi mov StartVector,eax Step: mov eax,X mov ecx,Y .if Xmin > Eax mov Xmin,eax .endif .if Xmax < Eax mov Xmax,eax .endif .if Ymin > Ecx mov Ymin,ecx .endif .if Ymax < Ecx mov Ymax,ecx .endif invoke NextVector, addr X, addr Y, addr Vector mov eax,Vector cmp StartVector,eax jne Step cmp X,esi jne Step cmp Y,edi jne Step ; Tg(Angle) = (Ymax - Ymin)/(Xmax - Xmin) finit fild Xmax fisub Xmin fild Ymax fisub Ymin fdiv st,st(1) ret Describe endp Entry proc invoke LoadImage, NULL, addr $Image, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE mov hBitmap,eax invoke CreateCompatibleDC, NULL mov hDC,eax invoke SelectObject, hDC, hBitmap invoke Describe ret Entry endp Ищет поверхность справа от левой стороны битмапы. Для картинки из первого поста возвращает значение Tg(G) = 3.05, в таблице tg(72°) = 3.0777. Полноценный механизм должен: o Определять углы линии(прямоугольника) и по ним вычислять угол. Для этого нужно найти места в которых сумма векторов наиболее сильно меняется. o Проверять валидность линии, для этого каждые N итераций проверять допуски изменения векторов. o Продолжать поиск поверхности слева от найденной. Этим способом можно и символы повёрнутые распознать. Например при описании цифры 3 на рисунке получится следующая последовательность векторов: UR R DR D LD RD N LD RD R RU U LU RU U LU L LD. Начало цепочки может смещаться(тоесть это кольцо), также при повороте ко всем векторам прибавляется константа. Это позволяет идентифицировать символ по таблице векторов.