Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > Анализ графической информации на чертеже


Автор: Racer 11.11.2010, 19:56
Добрый вечер, товарищи.

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

Суть: есть условный сканер, который "идет "по чертежу и ищет "пересечения". То есть если цвет пикселя черный, то это пересечение. Но на чертеж  могут быть "шумы" - когда его сканировали на хреновом сканере. Их надо отфильтровывать. Я делаю так: циклами иду по битмапу и смотрю пиксели. Когда нашел точку пересечения, смотрю вокруг- если хоть в 1 из 8 пикселей есть тоже черный пиксель- то это мы попали на линии и ее нужно засчитать. (см. картинку) Если вокруг нет- то это считается одиночной точкой, то есть шумом.

Схема: http://dl.dropbox.com/u/8382381/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0.jpg

Проблема: не все линии вылавливает. А это критично. По теории, если линия идет допустим под неким углом, то она будет красить пиксели, лежащие вкруг(хотя бы один) На схеме: мы нашли пересечение в центральном пикселе. затем смотрим вокруг- начиная слева сверху. на схеме мы найдем пересечение еще и вверху над найденным 1 пикселем. и должны засчитать это линией. Но на практике почему не всегда так. Пропускает линии.

Помогите пожалуйста. Если можете, укажите на ошибки в моем алгоритме или предложите свой. Необходимо забирать все линии (макс недобор - 0,5%)и фильтровать шумы(макс взятых шумов от всех - 0,5%). 

Пример http://dl.dropbox.com/u/8382381/%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80.jpg

Автор: VictorTsaregorodtsev 11.11.2010, 21:34
Гуглите алгоритмы векторизации.
Хотя, вообще-то, чертежного софта с такими возможностями должно быть много. В России начало бума перевода старых бумажных чертежей в цифру пришлось на середину 90х - т.е. и промышленного, и самописного софта должен быть вагон и маленькая тележка

Автор: Racer 11.11.2010, 22:06
Ну вагон или нет, меня знаете ли не интересует.

Спасибо погуглю, а замечаний по моему алгоритму нет?

Автор: Earnest 12.11.2010, 09:35
Цитата(Racer @  11.11.2010,  20:56 Найти цитируемый пост)
 Но на практике почему не всегда так. Пропускает линии.

99% ошибка реализации. Если, конечно, в линиях нет дырок. Если есть, сначала отфильтруй (залей дырки простейшим фильтром по соседям). 
Кстати, единичный шум можно убрать точно также (только наоборот - если у черного пиксела нет соседей, или мало - меньше заданного числа - убрать). А потом можно просто посчитать оставшиеся пикселы.
И еще. У тебя, что линии толщиной в один пиксел? 

Автор: _Y_ 12.11.2010, 10:26
В природе существует такая книжка http://www.labirint.ru/books/163324/#. Сам язык LabVIEW врядли заинтересует, но в книжке каждая тема состоит из двух частей: сначала хорошее описание принципов, а только потом реализация на LabVIEW. Вот эти-то пронципы и помогут решить проблему.

Автор: Racer 13.11.2010, 00:48
Линии не обязательно толщиной в 1 пиксель.

мой код:
Код

  for y := 1 to Round((hei-1) / step) do
    for x := 1 to Round((wid-1) / step) do
    begin
      xx:= x*step;
      yy:= y*step;

      if (xx) >=wid then Continue;
      if (yy) >= hei then Continue;

      microCount:= 0;
      for k := 0 to step-1 do
      begin
        xk:= xx + k;
        yk:= yy;
        Application.ProcessMessages;
        Bar.Position:= Bar.Position + 1;
        red:=   R(GetPixel(BM.Canvas.Handle, xk, yk));
        green:= G(GetPixel(BM.Canvas.Handle, xk, yk));
        blue:=  B(GetPixel(BM.Canvas.Handle, xk, yk));

        // если нет ничего - след. проход :
        if (red<>0) or (green<>0) or (blue<>0) then
          Continue;

        // слева вверху :
        red:=   R(GetPixel(BM.Canvas.Handle, xk-Fk, yk-Fk));
        green:= G(GetPixel(BM.Canvas.Handle, xk-Fk, yk-Fk));
        blue:=  B(GetPixel(BM.Canvas.Handle, xk-Fk, yk-Fk));
        if (red<>255) and (green<>255) and (blue<>255) then
        begin
          Inc(microCount);
          if microCount = 1 then
            lk:= k;
          Continue;
        end;



        // слева :
        red:=   R(GetPixel(BM.Canvas.Handle, xk-Fk, yk));
        green:= G(GetPixel(BM.Canvas.Handle, xk-Fk, yk));
        blue:=  B(GetPixel(BM.Canvas.Handle, xk-Fk, yk));
        if (red<>255) and (green<>255) and (blue<>255) then
        begin
          Inc(microCount);
          if microCount = 1 then
            lk:= k;
          Continue;
        end;

        // справа :
        red:=   R(GetPixel(BM.Canvas.Handle, xk+Fk, yk));
        green:= G(GetPixel(BM.Canvas.Handle, xk+Fk, yk));
        blue:=  B(GetPixel(BM.Canvas.Handle, xk+Fk, yk));
        if (red<>255) and (green<>255) and (blue<>255) then
        begin
          Inc(microCount);
          if microCount = 1 then
            lk:= k;
          Continue;
        end;



        // вверху :
        red:=   R(GetPixel(BM.Canvas.Handle, xk, yk-Fk));
        green:= G(GetPixel(BM.Canvas.Handle, xk, yk-Fk));
        blue:=  B(GetPixel(BM.Canvas.Handle, xk, yk-Fk));
        if (red<>255) and (green<>255) and (blue<>255) then
        begin
          Inc(microCount);
          if microCount = 1 then
            lk:= k;
          Continue;
        end;

        // справа вверху :
        red:=   R(GetPixel(BM.Canvas.Handle, xk+Fk, yk-Fk));
        green:= G(GetPixel(BM.Canvas.Handle, xk+Fk, yk-Fk));
        blue:=  B(GetPixel(BM.Canvas.Handle, xk+Fk, yk-Fk));
        if (red<>255) and (green<>255) and (blue<>255) then
        begin
          Inc(microCount);
          if microCount = 1 then
            lk:= k;
          Continue;
        end;

        // слева внизу :
        red:=   R(GetPixel(BM.Canvas.Handle, xk-Fk, yk+Fk));
        green:= G(GetPixel(BM.Canvas.Handle, xk-Fk, yk+Fk));
        blue:=  B(GetPixel(BM.Canvas.Handle, xk-Fk, yk+Fk));
        if (red<>255) and (green<>255) and (blue<>255) then
        begin
          Inc(microCount);
          if microCount = 1 then
            lk:= k;
          Continue;
        end;

        // снизу :
        red:=   R(GetPixel(BM.Canvas.Handle, xk, yk+Fk));
        green:= G(GetPixel(BM.Canvas.Handle, xk, yk+Fk));
        blue:=  B(GetPixel(BM.Canvas.Handle, xk, yk+Fk));
        if (red<>255) and (green<>255) and (blue<>255) then
        begin
          Inc(microCount);
          if microCount = 1 then
            lk:= k;
          Continue;
        end;

        // справа снизу :
        red:=   R(GetPixel(BM.Canvas.Handle, xk+Fk, yk+Fk));
        green:= G(GetPixel(BM.Canvas.Handle, xk+Fk, yk+Fk));
        blue:=  B(GetPixel(BM.Canvas.Handle, xk+Fk, yk+Fk));
        if (red<>255) and (green<>255) and (blue<>255) then
        begin
          Inc(microCount);
          if microCount = 1 then
            lk:= k;
          Continue;
        end;
      end;

      // если есть попадания - граф инфа :
      if (microCount < step) and (microCount <> 0) then begin
        Inc(Count);
        if NeedDraw then
        Image1.Canvas.Ellipse(lk+xx-10, lk+yy-10,
          lk+xx+10, lk+yy+10);
      end;
    end;


Может где и ошибся, только не могу найти smile

Автор: Racer 14.11.2010, 23:06
Никто мне не поможет?
Очень надо, плиз!

Автор: Pavia 14.11.2010, 23:33
  microCount:= 0;
      for k := 0 to step-1 do
      begin
        xk:= xx + k;
        yk:= yy; - тоже менять надо надо .

Автор: Racer 15.11.2010, 20:06
Оно меняется. просто есть аналогичная вторая часть, в которой меняются таким образом y а х остается как здесь у.
Как бы сначала горизонтальный проход, а затем вертикальный.

Автор: setnull 26.1.2012, 11:36
Цитата(Racer @ 13.11.2010,  00:48)
мой код:
Код

      xx:= x*step;
        xk:= xx + k;
    end;


Сильно не вникал, но показалось, что анализируются соседи только для одного из 4ех секторов?

Код

      xx:= (x+0.5)*step;
        xk:= xx + k - step div 2;


это если именно по Вашему алгоритму.
А вообще, действительно лучше просто пропустить изображение через какой подходящий к требованиям задачи фильтр


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)