Помощь - Поиск - Пользователи - Календарь
Полная версия: рекурсивный обход всех пикселей картинки
Форум «Всё о Паскале» > Delphi, Assembler и другие языки. > Delphi
Rian
сдрасте экспериментирую с распознаванием образов...
вобщем на картинке есть фигура (условно элипс)синего цвета
надо определить границы этой фигуры (верх-низ тд)

я нахожу любой синий пиксел и рекурсивно обхожу все соседние, перерисовывая в красный каждый проверенный

вот ток с возвратом результата что не так
подскажите где меня заклинило))


procedure analiz_pict(const image:timage;vis:tvis);
var
x,y,z:integer;
circles:array of TRect;

  function place_circ(const image:timage;x,y:integer):trect;
  var
  tempr:trect;
  begin
  result.Left:=x;
  result.Top:=y;
  result.Right:=x;
  Result.Bottom:=y;

  image.Canvas.Pixels[x,y]:=255;
  image.Invalidate;

  {if x<Result.Left then result.Left:=x;
  if x>result.Right then Result.Right:=x;
  if y<Result.Top then result.Top:=y;
  if y>Result.Bottom then Result.Bottom:=y;}


    if GetBValue(image.Canvas.Pixels[x-1,y])=255 then begin
    tempr:=place_circ(image,x-1,y);
    if tempr.Left<Result.Left then Result.Left:=tempr.Left;
    end;

    if GetBValue(image.Canvas.Pixels[x+1,y])=255 then begin
    tempr:=place_circ(image,x+1,y);
    if tempr.Right>Result.Right then Result.Right:=tempr.Right;
    end;

    if GetBValue(image.Canvas.Pixels[x,y-1])=255 then begin
    tempr:=place_circ(image,x,y-1);
    if tempr.top<Result.top then Result.top:=tempr.top;
    end;

    if GetBValue(image.Canvas.Pixels[x,y+1])=255 then begin
    tempr:=place_circ(image,x,y+1);
    if tempr.Bottom<Result.Bottom then Result.Bottom:=tempr.Bottom;
    end;
  end;
  label ex;
begin
  for x:=1 to image.Width-1 do
  for y:=1 to image.Height-1 do
  begin
  //z:=GetBValue(image.Canvas.Pixels[x,y]);
  //z:=0;
  if GetBValue(image.Canvas.Pixels[x,y])=255  then
  begin
  SetLength(circles,1);
  circles[0]:=place_circ(image,x,y);
  goto ex;
  end;
  end;
  ex: z:=0
end;



ps. похоже перегнул... попробую делать проверку для каждой грани отдельной функцией с частичной заменой цвета а не полной
Lapp
А что эта тема делает в Задачах?
Перенести в Delphi?
Rian
Цитата(Lapp @ 7.01.2010 1:40) *

Перенести а Delfi?


ой... может быть, хотя картинку можно воспринимать как массив
хотя кажется скоро доделаю
проблема тут:


result.Left:=x;
  result.Top:=y;
  result.Right:=x;
  Result.Bottom:=y;



и вот тут (для нижней границы проверяю через (<)

if GetBValue(image.Canvas.Pixels[x,y+1])=255 then begin
    tempr:=place_circ(image,x,y+1);
    if tempr.Bottom<Result.Bottom then Result.Bottom:=tempr.Bottom;


volvo
Непонятны 2 вещи:
во-первых, с чего ты решил, что для определения "синий цвет" достаточно, чтобы GetBValue было равно 255? У белого оно тоже 255. Сравнивай с синим цветом:
if image.Canvas.Pixels[x,y]=clBlue then ...


А во-вторых, для того, чтобы определить границы эллипса, недостаточно проверить ТОЛЬКО точки, находящиеся строго вверху, внизу, слева и справа. Надо еще проверять и угловые: выше-левее, ниже-левее, выше-правее, ниже-правее. Вот это, к примеру, выдает правильные границы эллипса:

procedure analiz_pict(const image:timage);

  function place_circ(const image:timage;x,y:integer):trect;
  const
    delta: array[1 .. 8] of record dx, dy: integer; end =
    (
      (dx:0; dy:1),
      (dx:1; dy:0),
      (dx:0; dy:-1),
      (dx:-1; dy:0),
      (dx:1; dy:1),
      (dx:1; dy:-1),
      (dx:-1; dy:1),
      (dx:-1; dy:-1)
    );

  var
  tempr:trect;
  i: integer;
  begin
    with result do
    begin
      Left := x; Top := y;
      Right := x; Bottom := y;
    end;
    image.Canvas.Pixels[x, y] := 255;
    image.Invalidate;

    for i := 1 to 8 do
    begin
      if image.Canvas.Pixels[x+delta[i].dx,y+delta[i].dy] = clBlue then begin
        tempr := place_circ(image, x+delta[i].dx,y+delta[i].dy);
        if tempr.Left < result.left then result.Left := tempr.Left;
        if tempr.right > result.right then result.right := tempr.right;
        if tempr.top < result.top then result.top := tempr.top;
        if tempr.bottom > result.bottom then result.bottom := tempr.bottom;
      end;
    end;
  end;

var
  x,y,z:integer;
  circles:array of TRect;

  label ex;
begin
  for x:=1 to image.Width-1 do
    for y:=1 to image.Height-1 do
    begin
      if image.Canvas.Pixels[x,y]=clBlue then
      begin
        SetLength(circles,1);
        circles[0]:=place_circ(image,x,y);
        showmessage(
          format('left:%d, top:%d, right:%d, bottom:%d',
          [circles[0].left, circles[0].Top, circles[0].Right, circles[0].Bottom])
        );
        goto ex;
      end;
    end;
  ex:
  z:=0
end;
Rian
респект!!! красиво...)
ну мне достаточно проверить только синий канал потому что я его уже отфильтровал (тип как на картинке)
и возможно он не обязательно будет чистым синим (сам еще не знаю)


вопрос
для чего проверять диагонали 159 753? если проверять крестом то для 5 проверяются 4268 для 4-12...
123
456
789
или например по диоганалям впринципе можно за границы области выйти
000х
00х1
0х11
х111

я результат более менее подходящий получил... выдает такое же самое
только почему все цифры на 1 меньше реальных?

canvas же считает от 1 а не от 0? почему так?
volvo
Цитата
canvas же считает от 1 а не от 0?
С чего бы? Всегда с 0 индексация была...
Цитата
для чего проверять диагонали 159 753? если проверять крестом то для 5 проверяются 4268 для 4-12...
Для того, чтобы найти фигуру, надо проверять всех ближайших соседей точки.
Rian
Цитата(volvo @ 7.01.2010 12:43) *

С чего бы? Всегда с 0 индексация была...
Для того, чтобы найти фигуру, надо проверять всех ближайших соседей точки.

мда с 0... засчитался wacko.gif
но диагонали мне не подойдут:

_111___
11111___
11111___
_____1111
_____1111

вариант маловероятный, но возможный
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.