OMarks - библиотека оптических маркеров Как подключить ?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

OMarks - библиотека оптических маркеров Как подключить ?

Сообщение Alex2013 » 04.12.2017 23:20:20

На днях обнаружил в дебрях интернета вот такую полезную мне библиотеку :
OMarks - библиотека оптических маркеров

Решает множество проблем с поиском маркера для ДР и работает если смотреть на пример (http://intbusoft.com/download/CameraOpenCV.zip) быстро и надежно .

Одна беда не получается прикрутить ее к коду на Лазарусе
Подключение простое как двери
Код: Выделить всё
  const
    External_library='OMarks.dll'; {Setup as you need}

  Type
  //Pchar  = ^char;
  Plongint  = ^longint;

  const
    OMARKS_TYPE_SMALL_AZTEC = $01;   
  { Params }
    OMARKS_IMAGE24 = $01;   
    OMARKS_IMAGE8 = $02;   
    OMARKS_IMAGE32 = $20;   
    OMARKS_QUALITY_1 = $04;   
    OMARKS_QUALITY_2 = $08;   
    OMARKS_QUALITY_3 = $10;   
  { Dinamic }
    DMARK_TREMBLE = $100;   
    DMARK_MOTION = $200;   
  {
     Function FindMarkers finds markers on image.
     0  - No Markers.
     1  - Markers.
     2  - Unknown image format.
     3  - Unknown type marker.
     4  - Unknown quality.
     5  - Error recognition.
   }

  { Result }
    const
    MAX_CHAR = 4000;

{  type
    MARKER = record
        len : longint;
        result : array[0..(MAX_CHAR)-1] of char;
        Points : array[0..3] of CvPoint;
      end;
}
  function FindMarkers(Image_Data:Pchar; Image_Width:longint; Image_Height:longint;
              All_Markers:Plongint;  Data_Result:PPchar;
             Size_Data_Result:PPlongint; Points4_Mark:PPlongint;
             Type_Marker:longint; Param:longint):longint;
//cdecl;
stdcall;
external External_library name 'FindMarkers';

  function DMarksInit:pointer;stdcall;  //cdecl;
external External_library name 'DMarksInit';

  procedure DMarksRelease(Marks:Ppointer); stdcall;  //cdecl;
external External_library name 'DMarksRelease';

  procedure DMarksProcessed(Image_Data:Pchar; Image_Width:longint; Image_Height:longint; Marks:Ppointer; All_Markers:Plongint;
              Data_Result:PPchar; Size_Data_Result:PPlongint;
              Points4_Mark:PPlongint; flags:longint); stdcall;  //cdecl;
external External_library name 'DMarksProcessed';


Вызов еще проще (Image1 обычная картинка ТImage )
Код: Выделить всё
procedure TMainForm.Button1Click(Sender: TObject);
Var
  AM,I:Longint;
  Size_Data_Result: Array[0..9] of Longint;
  Points4_Mark: Array[0..9] of PLongint ;
  Data_Result: Array[0..9] of Pchar;
  B8:TBitmap;
  DM:Pointer;
begin
  B8:=TBitmap.Create;
  //b8.PixelFormat:=pf8bit;
  b8.PixelFormat:=pf24bit;
  b8.SetSize(Image1.Picture.Bitmap.width, Image1.Picture.Bitmap.height);
  b8.Canvas.Draw(0,0,Image1.Picture.Bitmap);

AM:=10;
For I:=0 to 9 do begin
    Size_Data_Result[i]:=400;//?
    GetMem(Data_Result[i],400);
    GetMem(Points4_Mark[i],Sizeof(Longint)*8);
end;

B8.BeginUpdate;
I:=FindMarkers( Pointer(B8.RawImage.Data),
   B8.width, B8.height,
   @AM,@Data_Result,@Size_Data_Result,
   @Points4_Mark, OMARKS_TYPE_SMALL_AZTEC,
   OMARKS_IMAGE24 or  OMARKS_QUALITY_1);
{ ------------------------------------------------------------------------
// DMarksProcessed(  якобы улучшает  результат но без него работать тоже по идее должно ..
DMarksProcessed( Pointer(B8.RawImage.Data),
   B8.width, B8.height,@DM,
   @AM,@Data_Result,@Size_Data_Result,
   @Points4_Mark,
   OMARKS_IMAGE24 or  OMARKS_QUALITY_1);

DMarksRelease(DM);
------------------------------------------------------------------------------------ }
B8.ENDUpdate;
  ShowMessage(IntToStr(I)+' '+IntToStr(AM)  );
  For I:=0 to 9 do begin
    FreeMem(Data_Result[i],400);
    FreeMem(Points4_Mark[i],Sizeof(Longint)*8);
end;
  b8.Free;
end;

Но не фурычит ! Выбивает с исключением хотя если неверно задать flags FindMarkers возвращает правильные ошибки
(То есть в DLL заходит) Если убрать cdecl; (или stdcall;) успевает выдать 0 (что еще понятно )и все рано выбивает или 2 (что совсем непонятно )
хотя картинка гарантированно содержит Aztec метку ,

Вообщем полночи сегодня провозился но понять в чем дело не вышло .
Зы
Кроме OMarks.dll есть еще и OMarks.Lib может лучшее попытаться ее использовать ?
Последний раз редактировалось Alex2013 04.12.2017 23:44:21, всего редактировалось 3 раз(а).
Alex2013
энтузиаст
 
Сообщения: 710
Зарегистрирован: 03.04.2013 11:59:44

Re: OMarks - библиотека оптических маркеров Как подключить ?

Сообщение serbod » 04.12.2017 23:30:20

Код: Выделить всё
Size_Data_Result: Array[0..9] of Longint;
...
For I:=0 to 99 do begin
    Size_Data_Result[i]:=400;//?


Включи в настройках компилятора Range check, он будет бить тебя по рукам.
Аватара пользователя
serbod
постоялец
 
Сообщения: 215
Зарегистрирован: 16.09.2016 11:03:02
Откуда: Минск

Re: OMarks - библиотека оптических маркеров Как подключить ?

Сообщение Alex2013 » 04.12.2017 23:35:47

serbod писал(а):...
Включи в настройках компилятора Range check, он будет бить тебя по рукам.


Ну это я уже потом "ничтоже суметясь" накрутил и не дописал в начале было так:
Код: Выделить всё
AM:=10;
For I:=0 to 9 do begin
    Size_Data_Result[i]:=400;//?...

Сори "копипастнул" не глядя ... (исправил ) Но результат тот же .Эх если бы все было так просто ! :roll:
Alex2013
энтузиаст
 
Сообщения: 710
Зарегистрирован: 03.04.2013 11:59:44

Re: OMarks - библиотека оптических маркеров Как подключить ?

Сообщение serbod » 05.12.2017 00:23:53

Судя по типам PPlongint (указатель на указатель) библиотека сама выделяет память для результата, а в параметр определен как "var All_Markers: PLongint" который можно перебирать при помощи арифметики указателей - Inc(All_Markers).

Если нет желания использовать арифметику указателей, то можно определить указатель на массив чисел:
Код: Выделить всё
type
  TLongintArray = array [0..9] of Longint;
  PLongintArray = ^TLongintArray;

и дальше использовать его:
Код: Выделить всё
var
  pAll_Markers: PLongintArray;
  pData_Result: PByteArray;
Аватара пользователя
serbod
постоялец
 
Сообщения: 215
Зарегистрирован: 16.09.2016 11:03:02
Откуда: Минск

Re: OMarks - библиотека оптических маркеров Как подключить ?

Сообщение Alex2013 » 05.12.2017 01:19:09

В архиве есть pdf-ка с русским описанием всех параметров так что гадать особенно не о чем
Функция распознает оптические маркеры на входном изображении.
Код: Выделить всё
int FindMarkers( char* Image_Data, int Image_Width, int Image_Height, int* All_Markers,char** Data_Result, int** Size_Data_Result,
                      int** Points4_Mark, int Type_Marker, int Param );

Параметры:
Image_Data – входное изображение в виде массива графических данных обычного (не
перевернутого, как в BMP) характера, может быть 8, 24, 32 битное, шаг строки считается как и в
BMP – кратным 4 байтам;
Image_Width – ширина изображения;
Image_Height – высота изображения;
All_Markers – указатель на максимальное количество принимаемых на выходе маркеров, функция
изменяет это значение на количество обнаруженных маркеров;
Data_Result – указатель на массив указателей символьного типа, в которые для каждого маркера
будет возвращаться декодированный текст, указатели должны указывать на ранее выделенные
области памяти;
Size_Data_Result – указатель на массив указателей на размеры буферов Data_Result, после
выполнения функции эти значения изменяются на размер декодированного текста;
Points4_Mark – указатель на массив указателей на массивы типа int из 8 элементов, которые после
выполнения функции будут содержать координаты маркера на изображения в порядке: X0, Y0, X1,
Y1, X2, Y2, X3, Y3;
Type_Marker – тип маркера, который требуется найти на изображении, пока поддерживается
только Small Aztec, поэтому обязательно должно быть – OMARKS_TYPE_SMALL_AZTEC;
Param – флаги:
OMARKS_IMAGE8 – 8 битное изображение (Серое);
OMARKS_IMAGE24 – 24 битное изображение (BGR);
OMARKS_IMAGE32 – 32 битное изображение (BGR);
OMARKS_QUALITY_1 – качество распознавание 1;
OMARKS_QUALITY_2 – качество распознавание 2;
OMARKS_QUALITY_3 – качество распознавание 3;
От 1 до 3 увеличивается качество, но снижается производительность.

Функция возвращает 0, если маркеров не обнаружено. 1 – если обнаружен один или более
маркеров, 2 – неизвестный формат изображения, 3 – неизвестный типа маркера, 4 – неизвестная
ошибка, 5 – ошибка распознавания.


Меня больше волнует фокус с cdecl; и stdcall; ... Может вообще другой модификатор нужен ?
Зы
Заменить All_Markers:Plongint; на var All_Markers:longint; пробовал - реакции ноль !
Зы Зы Как Либ приликовать ? { $L OMarks.Lib} {$LINKLIB OMarks.Lib} ?

Добавлено спустя 13 часов 26 минут 40 секунд:
Добился что программа не вылетает пока не найден aztec-код ...
Подключил камеру .
Теперь можно "пугать" программу "страшным " кодом . :D

ИзображениеИзображение

:arrow: Все это безобразие (с исходниками) можно скачать ТУТ (Test_aztecl_002.7z)
Alex2013
энтузиаст
 
Сообщения: 710
Зарегистрирован: 03.04.2013 11:59:44

Re: OMarks - библиотека оптических маркеров Как подключить ?

Сообщение Alex2013 » 08.12.2017 18:57:36

Ура, она все таки верится ! :D
Дело было в том я что смотрел в пример, а не в документацию ...
(Сказано "Указатель на массив указателей" для всех предаваемых массивов вот так и делать нужно ... )

ИзображениеИзображение
Однако, что-то в датском королевстве еще по прежнему не так !

ИзображениеИзображение

Первый код нормально читает, а второй косо !
Дополнительная обработка (DMarksProcessed ) пока не работает ...


Сейчас залью на шару ...
:arrow: Test_aztecl_004.7z

Зы
Ко всему прочему еще и тормоз изрядный получился ....
(В прочем возможно это мой тестовый код для подготовки данных и их проверки притормаживает... Надо проверить ! )

Добавлено спустя 20 часов 46 минут 4 секунды:
Да не покинет оптимизм наших оптимизаторов ! :D

Выкинул тонну лишнего кода (скорость работы выросла заметно ) подключил DMarksProcessed и нарисовал "хитрую" упрощенную метку на бумаге .
(нарисовано кривовато но находит, хотя не очень уверенно )

ИзображениеИзображение

ИзображениеИзображение
Находит до трех меток одновременно но данные читает только с первой найденной (в чем дело пока не понял ).
Вообще видимо и сама библиотека изрядно глючная (гонял пример он тоже временами виснет и выбивает при работе с несколькими метками )
Но есть идея как это исправить (давать на "съедение" только один заранее найденный контур)

:arrow: Test_aztecl_005.7z :idea:

ЗЫ
"Хитрые метки" на основе Aztec Marker брать ТУТ
Alex2013
энтузиаст
 
Сообщения: 710
Зарегистрирован: 03.04.2013 11:59:44

Re: OMarks - библиотека оптических маркеров Как подключить ?

Сообщение Alex2013 » 11.12.2017 03:49:45

Вообщем ясно, что ничего непонятно .... :D
Мой текущий код модуля для интерфейса с библиотекой OMarks. :idea:
Что происходит с чтением Aztec кода в найденных метках кроме самой первой непонятно
но вообщем работает ...
Добавлена функция-оболочка .
Function FindMarkers_Pas(B:TBitmap;Var AM:Longint; DataResult:TStringList;PointsMark:Tlist;FL:byte):Integer;
(AM количество найденных меток PointsMark список указателей на Array[0..7] of longint fl-флаг качества( OMARKS_QUALITY_XXX) прочие понятно... )
Код: Выделить всё

unit OMarks;
interface
Uses Windows, Messages, SysUtils, Variants, Classes, Graphics;
{
  Automatically converted by H2Pas 1.0.0 from OMarks.h
  The following command line parameters were used:
    OMarks.h
    -D
}

  const
    External_library='OMarks.dll'; {Setup as you need}

  Type
  //Pchar  = ^char;
  Plongint  = ^longint;
{$IFDEF FPC}
{$PACKRECORDS C}
{$ENDIF}


  {*****************************************************************************
     (C) 2013. IntBuSoft. http://intbusoft.com
     OMarks.h - version 1.0      
  ****************************************************************************** }
(** unsupported pragma#pragma once*)
  { Type Code }

  const
    OMARKS_TYPE_SMALL_AZTEC = $01;   
  { Params }
    OMARKS_IMAGE24 = $01;   
    OMARKS_IMAGE8 = $02;   
    OMARKS_IMAGE32 = $20;   
    OMARKS_QUALITY_1 = $04;   
    OMARKS_QUALITY_2 = $08;   
    OMARKS_QUALITY_3 = $10;   
  { Dinamic }
    DMARK_TREMBLE = $100;   
    DMARK_MOTION = $200;   
  {
     Function FindMarkers finds markers on image.
     0  - No Markers.
     1  - Markers.
     2  - Unknown image format.
     3  - Unknown type marker.
     4  - Unknown quality.
     5  - Error recognition.
   }

  { Result }
    const
          MAX_CHAR = 4000;

{  type
    MARKER = record
        len : longint;
        result : array[0..(MAX_CHAR)-1] of char;
        Points : array[0..3] of CvPoint;
      end;
}
  function FindMarkers(Image_Data:Pchar; Image_Width:longint; Image_Height:longint;
              All_Markers:Plongint;  Data_Result:PPchar;
             Size_Data_Result:PPlongint; Points4_Mark:PPlongint;
             Type_Marker:longint; Param:longint):int16;
//cdecl;
stdcall;
external External_library name 'FindMarkers';

  function DMarksInit:pointer;stdcall;  //cdecl;
external External_library name 'DMarksInit';

  procedure DMarksRelease(Marks:Ppointer);stdcall;  //cdecl;
external External_library name 'DMarksRelease';

  procedure DMarksProcessed(Image_Data:Pchar; Image_Width:longint; Image_Height:longint; Marks:Ppointer; All_Markers:Plongint;
               Data_Result:PPchar; Size_Data_Result:PPlongint;
              Points4_Mark:PPlongint; flags:longint);stdcall;  //cdecl;
external External_library name 'DMarksProcessed';

Function FindMarkers_Pas(B:TBitmap;Var AM:Longint; DataResult:TStringList;PointsMark:Tlist;FL:byte):Integer;

implementation
// Converts 24 bit image to 8 bit grayscale
procedure GrayScale8bit( Clip: TBitmap;BB:Pointer);
var P0: PByteArray;
    P1: PByteArray;
    Gray,X,Y,I: integer;
    //Tmp: TBitmap;
begin
I:=0;
P1:=BB;
  for Y:=0 to pred(Clip.Height) do
    begin
      P0:=Clip.ScanLine[Y];
      for X:=0 to pred(Clip.Width) do
        begin
          Gray:=Round(P0^[X*3]*0.11+P0^[X*3+1]*0.59+P0^[X*3+2]*0.3);
          P1^[i]:=Byte(Gray);
          Inc(I)
        end;
    end;
end;

Function FindMarkers_Pas(B:TBitmap;Var AM:Longint; DataResult:TStringList;PointsMark:Tlist;FL:byte):Integer;

Const
  MAX_MARKERS_GREW=10;
  RMaX=9;
  MMax=RMaX+MAX_MARKERS_GREW;


Type
   AR=Array[0..7] of longint;
   TL = Array[0..MMax] of PLongint;
   PL = Array[0..MMax] of ^Ar ;
   PC=  Array[0..MMax] of PChar ;
Var
  C:TCanvas;
  J,I:Longint;
  //M:Array[0..9] of Trect;
  Size_Data_Result:^TL;
  Points4_Mark:^PL;
  Data_Result:^Pc;
  B8:TBitmap;
  DM,bb:Pointer;
  S:String;

Procedure Mem_Free;
var I:Integer;
Begin
FreeMem(bb,B8.height*B8.Width);
bb:=Nil;
  For I:=0 to mmax do begin
    Dispose(Size_Data_Result^[i]);
    FreeMem(Data_Result[i],400);
    FreeMem(Points4_Mark[i],Sizeof(Longint)*10);
end ;


Dispose(Size_Data_Result);
Dispose(Points4_Mark);
Dispose(Data_Result);
end;
Var
Arp:^AR;

begin
B8:=b;

// Выделяю память ...
AM:=RMax+1;
New(Size_Data_Result);
New(Points4_Mark);
New(Data_Result);

For I:=0 to MMax do begin
    New(Size_Data_Result^[i]);
if  i <=MMax-10 then  Size_Data_Result^[i]^:=400
else Size_Data_Result^[i]^:=0;//?
    GetMem(Data_Result^[i],400);
    GetMem(Points4_Mark^[i],Sizeof(Longint)*10);
end;
//BB:=b8.ScanLine[0];
GetMem(bb,B8.height*B8.Width);
GrayScale8bit(B8,bb);

// Поиск метки
Try
I:=FindMarkers(BB,
   B8.width, B8.height,
   @AM,Pointer(Data_Result),Pointer(Size_Data_Result),
   Pointer (Points4_Mark), OMARKS_TYPE_SMALL_AZTEC,
      fl or OMARKS_IMAGE8
  );
Result :=I;

if AM>0 Then begin
dm:=DMarksInit;
DMarksProcessed( BB,
   B8.width, B8.height,@DM,
   @AM,Pointer(Data_Result),Pointer(Size_Data_Result),
   Pointer (Points4_Mark),
   OMARKS_IMAGE8 or  OMARKS_QUALITY_3);
DMarksRelease(@DM);
End;

// Возврат результов
  if AM>0 Then
  for I:=0 to Am-1 do
    begin
  New(Arp);
  for J:=0 to 7 do ARP^[j]:=Points4_Mark^[i]^[j];
   PointsMark.Add(ARP);
  S:='';
  If (Size_Data_Result^[i]^>0) and ( Size_Data_Result^[i]^<=255) then
  for J:=0 to Size_Data_Result^[i]^-1 do S:=S+PChar(Data_Result^[i]+J)^
   else S:='-//-';
  DataResult.Add(S);
end;
//Очистка памяти
finally
  Mem_Free;
end;
end;
end.


Подключил к "Подзорной трубе"....
viewtopic.php?p=127408#p127408
Alex2013
энтузиаст
 
Сообщения: 710
Зарегистрирован: 03.04.2013 11:59:44


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

Рейтинг@Mail.ru