Выровнять изображение горизонтально

Тема в разделе "WASM.A&O", создана пользователем Tronix, 5 ноя 2010.

  1. Tronix

    Tronix Member

    Публикаций:
    0
    Регистрация:
    10 сен 2010
    Сообщения:
    122
    А вы бы воспользовались глазами и дочитали первое сообщение до конца. Распознавать я умею.
     
  2. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    также можно провести 2(исключаем проход одной из них между двумя штрихами) пересекающиеся диагонали диагонали
     
  3. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    > Как вы определите что пиксель принадлежит штриху, а не цифре к примеру без описания контура ?
    по размеру?
     
  4. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    Tronix
    ну, с такой реакцией и помогать не охота. думаю, вы воспользуетесь мозгами и сами все решите. распознавать же умеете.
     
  5. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Tronix
    Не под любым. Но градусов тридцать люфта допустимо.
     
  6. Tronix

    Tronix Member

    Публикаций:
    0
    Регистрация:
    10 сен 2010
    Сообщения:
    122
    Градусов 30 люфта у меня распознается. Главное чтобы хотябы одна линия прошлась по всем значащим точкам. Но хочется большего.
     
  7. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Tronix
    Попробуй повертеть штрихкод и подсчитать количество переходов белый-чёрный между соседними точками по горизонтали и вертикали, думаю что по соотношению этих двух чисел определить угол на который нужно поворачивать с точностью в пару десятков градусов будет несложно.
     
  8. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    Решение номер 0 (самое простое и без графов и князей).

    Предполагаем что функция распознавания достаточно вменяема и ее можно звать с сильно повернутой картинкой и она не похоронит всю систему повалившись в экцпшен (даже если так - апкладываем ее сехом и так долее). Зовем ее для начального состояния (примем что это некий угол A0).

    Далее поворачиваем кортинку и все время смотрим че функция вернула. Отклик может быть при неких углах (A0+-dA), гдк dA - небольшое отклонение от истинного угла A0. Таким образом функция вернет ряд правильных значений штрихкода на некотром интервале [A1,A2].

    Этот интервал можно найти перебором углов или умнее. Если надо, могу продолжить.

    Решение номер 2 (самое лучшее среди всех решений)

    Считываем всю кортинку в матрицу {Xi,Yi} - набор точек на плоскости (черно-белый). Находим центр массо всех точков, это будет где-то в области середины штрих-кода.

    Далее действительно можно применять приближающий прямоугольнег или линии (но не ОДНУ ЛИНИЮ!!!) для поиска самого описывающего. Критерий - рекомендую Хи-квадрат он же Пирсон.
     
  9. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    Решение номер 3 (самое красивое)

    Считываем кортинко в виде матрицы. Далее предполагаем что мы знаем как генерируеца штрих-код и генерируем свою кортинку на основании аргумента 0 (было закодировано число 0). Пытаемся брутфосом - поворачивая свою или оригинальную кортинку - сопоставить обе и по критерию (выше) получить наиболее подходящую. В результате мы перебором как бы нарисуем ту же самую что и настоящая картинка под неким близким к истЕнному углу поворота.
     
  10. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Код (Text):
    1. NextPixel(X, Y, Vector):
    2.    dX, dY = [(+1, +1), (+1, -1), (-1, -1), (-1, +1)][Vector]
    3.    X = X + dX
    4.    Y = Y + dY
    5.    if POINT(X, Y)
    6.       Vector = (Vector + 1) && 3
    7.    else
    8.       dX, dY = [(-1,  0), (0, +1), (+1,  0), (0, -1)][Vector]
    9.       X = X + dX
    10.       Y = Y + dY
    11.       if !POINT(X, Y)
    12.          Vector = (Vector - 1) && 3
    13.    end
    14.  
    15. Describe(X, Y):
    16.    Vector = 0   ; Up
    17.    X0 = X
    18.    Y0 = Y
    19.    Xmin = X
    20.    Xmax = X
    21.    Ymin = Y
    22.    Ymax = Y
    23.    NextPixel(X, Y, Vector)
    24.    Do
    25.    if X < Xmin
    26.       Xmin = X
    27.    endif
    28.    if X > Xmax
    29.       Xmax = X
    30.    endif
    31.    if Y < Ymin
    32.       Ymin = Y
    33.    endif
    34.    if Y > Ymax
    35.       Ymax = Y
    36.    endif
    37.    NextPixel(X, Y, Vector)
    38.    Loop Vector | (X != X0) | (Y != Y0)
    39.    Angle = (Ymax - Ymin)/(Xmax - Xmin)
    40.    end
    Проверка приращения не показана. Также поиск пикселя справа не показан.
     
  11. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    имхо решение влоб
    сканируем попиксельно слева направо вдоль вертикали и ищем черный пиксель после которого на следующей строке идет
    черный, зная что цифры находятся определенно ниже нужного изображения, сканируем дальше пока не встретим белый пиксель после черного
    на основе запомненных двух пикселей из уравнения прямой находим tg(a), где а угол наклона картинки
    вертим ее как надо.
    либо находим перпендикуляр к этой линии и проходимся по нему смещенному вниз на пару пикселей
    выделяем координаты черных пикселей и на основании этих точек и факта перпендикулярности направляющего перпендикуляра получаем нужное изображение

    математика школы-первого курса
     
  12. Ravager

    Ravager New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2008
    Сообщения:
    34
    Можно просто подобрать положение изображения, при котором его высота, т.е. расстояние по вертикали между самым верхним и самым нижним чёрным пикселями, минимальна. Изображение может получиться перевёрнутым вверх ногами.
     
  13. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    Пытаемся распознать - не получилось - поворачиваем на 180 градусов - пытается распознать - не получилось - штрих код не корректный.
     
  14. AlexCab

    AlexCab New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2008
    Сообщения:
    142
    !Всё не читал, может баян.

    1.Понизить разрешение до <подобрать при наладке опримальное>.
    2.Выполнить серию сканирований (красным на картинке), с шагом <подобрать при наладке опримальное> градусов(без поворота кртинки),
    в результе получим некоторый набор чисел.
    3.Найти два лучших(наиблее похожих)(в том числе и меняя порядок следования знаков так как картинка может быть кверхногами),
    и выполнить несколько дополнительных сканирований(на картинке зелёным) между этими двумя лучшими(для подтверждения).
    4.Если подтвердить результат не удалось - повысить разрешение и к 2, иначе OK.

    ADD: Если штрих код может быть не в центре изображения, то его можно разбить на несколько участков и выполнить 2 для каждого их них.
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Набросал простейший код:
    Код (Text):
    1. IMAGE_WIDTH equ 707
    2. IMAGE_HEIGHT    equ 399
    3.  
    4. .data
    5. hBitmap HANDLE ?
    6. hDC     HANDLE ?
    7. .code
    8. $Image  CHAR "Scan.bmp",0
    9.  
    10. VECTOR_UP equ 0
    11. VECTOR_RIGHT equ 1
    12. VECTOR_DOWN equ 2
    13. VECTOR_LEFT equ 3
    14.  
    15. Point proc X:ULONG, Y:ULONG
    16.     mov eax,X
    17.     mov ecx,Y
    18.     test eax,eax
    19.     jl Over
    20.     test ecx,ecx
    21.     jl Over
    22.     cmp eax,IMAGE_WIDTH
    23.     mov edx,IMAGE_HEIGHT
    24.     ja Over
    25.     cmp ecx,edx
    26.     ja Over
    27.     sub edx,ecx
    28.     invoke GetPixel, hDC, Eax, Edx
    29.     cmp al,200
    30.     setb al
    31.     movzx eax,al
    32. @@:
    33.     ret
    34. Over:
    35.     xor eax,eax
    36.     jmp @b
    37. Point endp
    38.  
    39. NextVector proc uses ebx esi edi X:PULONG, Y:PULONG, Vector:PULONG
    40.     mov ebx,Vector
    41. Scan:
    42.     mov esi,X
    43.     mov edi,Y
    44.     mov eax,dword ptr [ebx]
    45.     mov esi,dword ptr [esi]
    46.     mov edi,dword ptr [edi]
    47.     add esi,dword ptr [FirstTable + eax*8]
    48.     add edi,dword ptr [FirstTable + eax*8 + 4]
    49.     invoke Point, Esi, Edi
    50.     test eax,eax
    51.     jnz Fpt
    52.     mov eax,dword ptr [ebx]
    53.     add esi,dword ptr [NextTable + eax*8]
    54.     add edi,dword ptr [NextTable + eax*8 + 4]
    55.     invoke Point, Esi, Edi
    56.     test eax,eax
    57.     jnz Load
    58.     dec dword ptr [ebx]
    59.     and dword ptr [ebx],11B
    60.     jmp Scan    ; Ext.
    61. ;   jmp Exit
    62. Fpt:
    63.     inc dword ptr [ebx]
    64. Load:
    65.     mov ecx,X
    66.     mov edx,Y
    67.     mov dword ptr [ecx],esi
    68.     mov dword ptr [edx],edi
    69. Exit:
    70.     and dword ptr [ebx],11B
    71.     ret
    72. ;      dX  dY
    73. FirstTable:
    74.     DD +1, +1
    75.     DD +1, -1
    76.     DD -1, -1
    77.     DD -1, +1
    78. NextTable:
    79.     DD -1,  0
    80.     DD  0, +1
    81.     DD +1,  0
    82.     DD  0, -1
    83. NextVector endp
    84.  
    85. FindPoint proc uses ebx esi edi X:PULONG, Y:PULONG, Vector:ULONG
    86.     mov ebx,Vector
    87.     mov esi,X
    88.     mov edi,Y
    89.     mov esi,dword ptr [esi]
    90.     mov edi,dword ptr [edi]
    91. @@:
    92.     add esi,dword ptr [VectorTable + ebx*8]
    93.     add edi,dword ptr [VectorTable + ebx*8 + 4]
    94.     invoke Point, Esi, Edi
    95.     test eax,eax
    96.     jz @b
    97.     mov ecx,X
    98.     mov edx,Y
    99.     mov dword ptr [ecx],esi
    100.     mov dword ptr [edx],edi
    101.     ret
    102. VectorTable:
    103.     DD  0, +1
    104.     DD +1,  0
    105.     DD  0, -1
    106.     DD -1,  0
    107. FindPoint endp
    108.  
    109. Describe proc
    110. Local X:ULONG, Y:ULONG
    111. Local Xp:ULONG, Yp:ULONG
    112. Local Vector:ULONG, StartVector:ULONG
    113. Local Xmin:ULONG, Xmax:ULONG, Ymin:ULONG, Ymax:ULONG
    114.     mov ebx,IMAGE_HEIGHT    ; Y для поиска поверхности справа.
    115. NextLine:
    116.     xor esi,esi
    117. NextPixel:
    118.     mov edi,ebx
    119.     invoke Point, Esi, Edi
    120.     test eax,eax
    121.     jnz @f
    122.     inc esi
    123.     cmp esi,IMAGE_WIDTH
    124.     jb NextPixel
    125.     dec ebx
    126.     jnz NextLine
    127.     Int 3
    128. @@:
    129.     mov X,esi
    130.     mov Y,edi
    131.     mov Vector,VECTOR_DOWN
    132.     invoke NextVector, addr X, addr Y, addr Vector
    133.     mov esi,X
    134.     mov edi,Y
    135.     mov eax,Vector
    136.     mov Xmin,esi
    137.     mov Xmax,esi
    138.     mov Ymin,edi
    139.     mov Ymax,edi
    140.     mov StartVector,eax
    141. Step:
    142.     mov eax,X
    143.     mov ecx,Y
    144.     .if Xmin > Eax
    145.     mov Xmin,eax
    146.     .endif
    147.     .if Xmax < Eax
    148.     mov Xmax,eax
    149.      .endif
    150.     .if Ymin > Ecx
    151.     mov Ymin,ecx
    152.     .endif
    153.     .if Ymax < Ecx
    154.     mov Ymax,ecx
    155.     .endif
    156.     invoke NextVector, addr X, addr Y, addr Vector
    157.     mov eax,Vector
    158.     cmp StartVector,eax
    159.     jne Step
    160.     cmp X,esi
    161.     jne Step
    162.     cmp Y,edi
    163.     jne Step
    164.    
    165. ;   Tg(Angle) = (Ymax - Ymin)/(Xmax - Xmin)
    166.     finit
    167.     fild Xmax
    168.     fisub Xmin
    169.     fild Ymax
    170.     fisub Ymin
    171.     fdiv st,st(1)
    172.     ret
    173. Describe endp
    174.  
    175. Entry proc
    176.     invoke LoadImage, NULL, addr $Image, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE
    177.     mov hBitmap,eax
    178.     invoke CreateCompatibleDC, NULL
    179.     mov hDC,eax
    180.     invoke SelectObject, hDC, hBitmap
    181.     invoke Describe
    182.     ret
    183. 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. Начало цепочки может смещаться(тоесть это кольцо), также при повороте ко всем векторам прибавляется константа. Это позволяет идентифицировать символ по таблице векторов.