PDA

Просмотр полной версии : Ис нова об распознавании картинок


Mirovan
18.01.2007, 21:53
Тема была затронута не раз. Но всё же.

Есть изображение: на странице http://l2top.ru/?voteme=1139&rating=full , требуется (как сбственно вы и догадались) распознать эту картинку.

При взгляде на это изображение срузу понятно что нет никакой защиты от распознавания - фон достаточно отличается от цвета цифр, цифры всегда имеют иди и тот же шрифт , размер и располагаются строго по центру.

Какой алгоритм здесь подойдет - распознавание по байтам или распознавание по шаблону (если кто знает четкий алгоритм скажите) ?

Mirovan
18.01.2007, 22:19
Начал писать код на пасе (делфи), возникла проблемка:

загружаю картинку со страницы 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;

zl0ba
18.01.2007, 23:16
Наверно не в той ветке создал эту тему. С формулируй вопрос правильней!

ZaCo
19.01.2007, 00:03
тут достаточно определить цвет цифр, а так цифры всегда стоят на одних и тех же местах просто берем точку с нужной координатой. но тут возможно наложении на нее шума, поэтому берем область одной из цифр размерами 5х5 и находим тот цвет который встречается чаще - это и будет искомый. делаем с этого всего битовую матрицу - 1-пиксель принадлежит цифре, 0 - не принадлежит. сравниваем количество точек при совмещении. все.

Mirovan
19.01.2007, 16:03
Может быть проще сравнивать по заранее готовому шаблону ? Именно так я и хочу сделать, т.е. у меня имеются 10 файлов с готовыми шаблонами цифр - от 0 до 9, такого же размера как и на примере картинки и четко черно-белого цвета, далее просто дело прямых рук написания кода для сравнения, с этим у меня проблем, думаю не будет.

Но вот проблемка в преобразовании цветной картинки JPeG в черно-белую BMP (код см. выше), не могу понять почему не работат, думаю что компонент делфи как то кривовато работает, может есть другой способ?

Mirovan
19.01.2007, 19:08
Вобщем с изобрадением я разобрался, вот код:


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-шной картинки получается монохромное изображение. Теперь задача его раскодировать

Abra
19.01.2007, 20:13
Теперь задача его раскодировать
))))))))))))
непредвиденное обстоятельство, да?))

Mirovan
19.01.2007, 20:48
Ну, вобщем приложение готово, работает по шаблону, всё очень просто

вот код


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 , но на этой основе можно забадяжить своё :)

Mirovan
19.01.2007, 20:50
))))))))))))
непредвиденное обстоятельство, да?))

Уже нет :)

nerezus
19.01.2007, 21:12
А такая красивая функция encodeImg(), аж прямо ужас

ZaCo
19.01.2007, 22:05
>>Может быть проще сравнивать по заранее готовому шаблону ?
как вы будете сравнивать с шаблоном если на изображении "мусор"?

Zadoxlik
19.01.2007, 22:38
тут достаточно определить цвет цифр, а так цифры всегда стоят на одних и тех же местах просто берем точку с нужной координатой. но тут возможно наложении на нее шума, поэтому берем область одной из цифр размерами 5х5 и находим тот цвет который встречается чаще - это и будет искомый. делаем с этого всего битовую матрицу - 1-пиксель принадлежит цифре, 0 - не принадлежит. сравниваем количество точек при совмещении. все.
я так капчу на твоем хомяке сломал :D

ZaCo
19.01.2007, 22:42
у меня даже проще, без шума и координатных растяжений\поворотов было :)

Zadoxlik
19.01.2007, 22:43
Точно :dddd

Mirovan
20.01.2007, 15:48
А такая красивая функция encodeImg(), аж прямо ужас

Выше говорилось что это функция специфична только для данной картинки, поэтому прошу строго не судить о названии функций :)

Mirovan
20.01.2007, 15:52
сам шум на этой картинке (http://l2top.ru - выберите сайт нажмите кнопку "мой выбор" чтобы увидеть картинку) представлен в другом цвете, именно поэтому я преобразовываю картинку в монохромный рисунок , что позводяет убрать шум .