Тема была затронута не раз. Но всё же. Есть изображение: на странице http://l2top.ru/?voteme=1139&rating=full , требуется (как сбственно вы и догадались) распознать эту картинку. При взгляде на это изображение срузу понятно что нет никакой защиты от распознавания - фон достаточно отличается от цвета цифр, цифры всегда имеют иди и тот же шрифт , размер и располагаются строго по центру. Какой алгоритм здесь подойдет - распознавание по байтам или распознавание по шаблону (если кто знает четкий алгоритм скажите) ?
Начал писать код на пасе (делфи), возникла проблемка: загружаю картинку со страницы http://l2top.ru/?voteme=1139&rating=full , сохраняю файлик как ЖПГ, открываю в mspaint, сохраняю как монохромный, плучается здорово ! Попытался реализовать аналогичное на делфи - не катит, получается все равно 24 бита: function JPEG2BMP(const JPGFile, BMPFile: string): boolean; var JPG: TJPEGImage; BMP: TBitmap; begin JPG:= TJPEGImage.Create; BMP:= TBitmap.Create; try JPG.LoadFromFile(JPGFile); BMP.PixelFormat:= pf1bit; BMP.Assign(JPG); BMP.SaveToFile(BMPFile); finally FreeAndNil(JPG); FreeAndNil(BMP); Result:= FileExists(BMPFile); end; end;
тут достаточно определить цвет цифр, а так цифры всегда стоят на одних и тех же местах просто берем точку с нужной координатой. но тут возможно наложении на нее шума, поэтому берем область одной из цифр размерами 5х5 и находим тот цвет который встречается чаще - это и будет искомый. делаем с этого всего битовую матрицу - 1-пиксель принадлежит цифре, 0 - не принадлежит. сравниваем количество точек при совмещении. все.
Может быть проще сравнивать по заранее готовому шаблону ? Именно так я и хочу сделать, т.е. у меня имеются 10 файлов с готовыми шаблонами цифр - от 0 до 9, такого же размера как и на примере картинки и четко черно-белого цвета, далее просто дело прямых рук написания кода для сравнения, с этим у меня проблем, думаю не будет. Но вот проблемка в преобразовании цветной картинки JPeG в черно-белую BMP (код см. выше), не могу понять почему не работат, думаю что компонент делфи как то кривовато работает, может есть другой способ?
Вобщем с изобрадением я разобрался, вот код: function setBWColor(c: TColor): TColor; begin if c > (255*255*255)/2 then c := clWhite else c := clBlack; Result := c; end; procedure TForm1.Button1Click(Sender: TObject); var h, w: Integer; begin for w := 0 to Image1.Width-1 do for h := 0 to Image1.Height-1 do Image1.Canvas.Pixels[w,h] := setBWColor(Image1.Canvas.Pixels[w,h]); end; В результате из BMP-шной картинки получается монохромное изображение. Теперь задача его раскодировать
Ну, вобщем приложение готово, работает по шаблону, всё очень просто вот код Code: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, jpeg, ExtDlgs; type TForm1 = class(TForm) Image1: TImage; Button1: TButton; OpenPictureDialog1: TOpenPictureDialog; Edit1: TEdit; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; TMas = array[1..210, 1..65] of Boolean; var Form1: TForm1; Mas: TMas; dir: String; implementation {$R *.dfm} function JPEG2BMP(const JPGFile, BMPFile: string): boolean; // Ôóíêöèÿ äëÿ êîíâåðòèðîâàíèÿ JPEG ôàéëà â <BMP> // JPGFile - èìÿ îòêðûâàåìîãî ôàéëà // BMPFile - èìÿ <ñîõðàíÿåìîãî> ôàéëà var JPG: TJPEGImage; BMP: TBitmap; begin JPG := TJPEGImage.Create; BMP := TBitmap.Create; try JPG.LoadFromFile(JPGFile); BMP.PixelFormat:= pf1bit; BMP.Assign(JPG); BMP.SaveToFile(BMPFile); finally FreeAndNil(JPG); FreeAndNil(BMP); Result := FileExists(BMPFile); end; end; function setBWColor(c: TColor): TColor; begin if c > (255*255*255)/2 then c := clWhite else c := clBlack; Result := c; end; function encodeImg(Mas: TMas): String; type Tfiles = array[0..9] of String; var f: Tfiles; i, j, k: Integer; shablon: array[1..32, 1..12] of Boolean; BMP: TBitmap; max, equal: Integer; temp, st: String; begin for i := 0 to 9 do f[i] := dir + '/shablon/' + IntToStr(i) + '.bmp'; BMP := TBitmap.Create; st := ''; max := 0; // 1 öèôðà for k := 0 to 9 do begin BMP.LoadFromFile(f[k]); for i := 1 to 32 do for j := 1 to 12 do if (BMP.Canvas.Pixels[i-1,j-1] = clWhite) then shablon[i,j] := true else shablon[i,j] := false; equal := 0; for i := 1 to 32 do for j := 1 to 12 do begin if shablon[i,j] = Mas[i+27,j+16] then equal := equal + 1; end; if (equal > max) then begin max := equal; temp := IntToStr(k); end; end; st := st + temp; max := 0; // 2 öèôðà for k := 0 to 9 do begin BMP.LoadFromFile(f[k]); for i := 1 to 32 do for j := 1 to 12 do if (BMP.Canvas.Pixels[i-1,j-1] = clWhite) then shablon[i,j] := true else shablon[i,j] := false; equal := 0; for i := 1 to 32 do for j := 1 to 12 do begin if shablon[i,j] = Mas[i+54,j+16] then equal := equal + 1; end; if (equal > max) then begin max := equal; temp := IntToStr(k); end; end; st := st + temp; max := 0; // 3 öèôðà for k := 0 to 9 do begin BMP.LoadFromFile(f[k]); for i := 1 to 32 do for j := 1 to 12 do if (BMP.Canvas.Pixels[i-1,j-1] = clWhite) then shablon[i,j] := true else shablon[i,j] := false; equal := 0; for i := 1 to 32 do for j := 1 to 12 do begin if shablon[i,j] = Mas[i+81,j+16] then equal := equal + 1; end; if (equal > max) then begin max := equal; temp := IntToStr(k); end; end; st := st + temp; max := 0; // 4 öèôðà for k := 0 to 9 do begin BMP.LoadFromFile(f[k]); for i := 1 to 32 do for j := 1 to 12 do if (BMP.Canvas.Pixels[i-1,j-1] = clWhite) then shablon[i,j] := true else shablon[i,j] := false; equal := 0; for i := 1 to 32 do for j := 1 to 12 do begin if shablon[i,j] = Mas[i+108,j+16] then equal := equal + 1; end; if (equal > max) then begin max := equal; temp := IntToStr(k); end; end; st := st + temp; max := 0; // 5 öèôðà for k := 0 to 9 do begin BMP.LoadFromFile(f[k]); for i := 1 to 32 do for j := 1 to 12 do if (BMP.Canvas.Pixels[i-1,j-1] = clWhite) then shablon[i,j] := true else shablon[i,j] := false; equal := 0; for i := 1 to 32 do for j := 1 to 12 do begin if shablon[i,j] = Mas[i+135,j+16] then equal := equal + 1; end; if (equal > max) then begin max := equal; temp := IntToStr(k); end; end; st := st + temp; max := 0; // 6 öèôðà for k := 0 to 9 do begin BMP.LoadFromFile(f[k]); for i := 1 to 32 do for j := 1 to 12 do if (BMP.Canvas.Pixels[i-1,j-1] = clWhite) then shablon[i,j] := true else shablon[i,j] := false; equal := 0; for i := 1 to 32 do for j := 1 to 12 do begin if shablon[i,j] = Mas[i+162,j+16] then equal := equal + 1; end; if (equal > max) then begin max := equal; temp := IntToStr(k); end; end; st := st + temp; Result := st; end; procedure TForm1.Button1Click(Sender: TObject); var h, w: Integer; Mas: TMas; begin OpenPictureDialog1.Execute; JPEG2BMP(OpenPictureDialog1.FileName, dir+'/temp/temp.bmp'); Image1.Picture.LoadFromFile(dir+'temp/temp.bmp'); for w := 0 to Image1.Width-1 do for h := 0 to Image1.Height-1 do begin Image1.Canvas.Pixels[w,h] := setBWColor(Image1.Canvas.Pixels[w,h]); if (Image1.Canvas.Pixels[w,h] = clWhite) then Mas[w+1, h+1] := true //áåëûé else Mas[w+1, h+1] := false; //÷åðíûé end; Edit1.Text := encodeImg(Mas); end; procedure TForm1.FormCreate(Sender: TObject); begin dir := ExtractFilePath(ParamStr(0)); end; end. p.s. работает только для картинки по адресу http://l2top.ru/?voteme=1139&rating=full , но на этой основе можно забадяжить своё
>>Может быть проще сравнивать по заранее готовому шаблону ? как вы будете сравнивать с шаблоном если на изображении "мусор"?
Выше говорилось что это функция специфична только для данной картинки, поэтому прошу строго не судить о названии функций
сам шум на этой картинке (http://l2top.ru - выберите сайт нажмите кнопку "мой выбор" чтобы увидеть картинку) представлен в другом цвете, именно поэтому я преобразовываю картинку в монохромный рисунок , что позводяет убрать шум .