|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Детектор границ Канни
Добрый день. Не могу понять в чём ошибка реализации детектора границ Кенни на Delphi6.
Во вложении исходные изображения, углы градиента, градиент и границы. Собель работает вроде верно - очень похоже на то что есть в инете по картинкам, определение углов тоже похоже на правду - стороны света определяются верно на простых перпендикулярных линиях 0-180 градусов с кратностью 45. Сам детектор построен по теории описанной везде - берём точку с углом и градиентом, сравниваем её с соседними точками у которых тот же угол (если 90 то идем вверх и вниз, если 45 то по диагонали проверяем точки), если угол тот же то проверяем градиент на больше/меньше - если у исследуемой точки больше чем у соседних то есть граница и на выходном битмапе ставим белую точку в координату исследуемой. Куски кода: код собеля Код:
FOR Y := BM1.Height-2 DOWNTO 2 DO // перебор матрицы c запасом по краям на 1 пиксель BEGIN i1 := BM1.ScanLine[Y-1]; // строка выше i0 := BM1.ScanLine[Y]; // исследуемая i2 := BM1.ScanLine[Y+1]; // ниже d := sobel.ScanLine[Y]; // результат sba:= sobang.ScanLine[Y]; // массив углов i := 3; // 3 байта на цвет FOR X := 2 TO BM1.Width-2 DO begin mgx:= -p1*i1^[i-3]-p2*i0^[i-3]-p1*i2^[i-3]; mgx:=mgx +p1*i1^[i+3]+p2*i0^[i+3]+p1*i2^[i+3]; mgy:= -p1*i1^[i-3]-p2*i1^[i]-p1*i1^[i+3]; mgy:=mgy +p1*i2^[i-3]+p2*i2^[i]+p1*i2^[i+3]; ang:=0; if mgx=0 then mgx:=0.00001; if (mgx=0)and(mgy=0) then ang:=0; if mgx<>0 then ang:=trunc(((180/3.1415926)*(ArcTan2(mgy,mgx)))); // if mgy=0 then mgy:=0.00001; // if (mgy=0)and(mgx=0) then ang:=0; // if mgy<>0 then ang:=trunc(((180/3.1415926)*(ArcTan2(mgx,mgy)))); mgx:=mgx*mgx; mgy:=mgy*mgy; grad:=trunc(sqrt(mgx+mgy)); // вычисляем градиент if grad<angmin then angmin:=grad; if grad>angmax then angmax:=grad; g:=grad; if grad>255 then g:=255; GistArray[g]:=GistArray[g]+g; if GistArray[g]>Gmax then begin Gmax:=GistArray[g]; // ищем максимум одинаковых данных Nmax:=g; // запомнили число end; if CheckBox6.Checked then // если надо порог считать, иначе без порога заносим в картинку if (grad > porog) then grad:= 255 else grad:= 0; if ((ang<=22)and(ang>=0))or ((ang>=-22)and(ang<=0))then iang:=30 // определяем все углы и им даём цвет else if (ang>22)and(ang<=67) then iang:=60 else if (ang>67)and(ang<=112) then iang:=90 else if (ang>112)and(ang<=158) then iang:=120 else if (ang<=180)and(ang>158)or((ang>=-180)and(ang<=-158)) then iang:=150 else if (ang>=-158)and(ang<-112) then iang:=180 else if (ang>=-112)and(ang<-67) then iang:=210 else if (ang>=-67)and(ang<=-22) then iang:=240; d^[i] := grad; sba^[i]:=iang; Inc(i); d^[i] := grad; sba^[i]:=iang; Inc(i); d^[i] := grad; sba^[i]:=iang; Inc(i); end; END; код канни Код:
FOR Y := sobel.Height-2 DOWNTO 2 DO // перебор матрицы c запасом по краям на 1 пиксель BEGIN g2 := sobel.ScanLine[Y-1]; g1 := sobel.ScanLine[Y]; // данные амплитуд градиента g0 := sobel.ScanLine[Y+1]; a2 := sobang.ScanLine[Y-1]; a1 := sobang.ScanLine[Y]; // данные углов a0 := sobang.ScanLine[Y+1]; e0 := Edgeout.ScanLine[Y]; // приёмное изображение i := 3; // 3 байта на цвет FOR X := 2 TO sobel.Width-2 DO begin e0^[i]:=0; // очищаем e0^[i+1]:=0; e0^[i+2]:=0; mgg:= g1^[i]; // взяли данные амплитуды mga:= a1^[i]; // взяли данные угла if mga=30 then //(ang<=45)and(ang>=0) // определяем все углы и им даём цвет begin mgg1:=g1^[i+3]; // направление --> -22+22 =0 mga1:=a1^[i+3]; if mga=mga1 then // если углы направления градиента совпали то выбираем наибольшее значение градиента if (mgg>mgg1)and(mgg>porog) then begin e0^[i]:=255;e0^[i+1]:=255;e0^[i+2]:=255; end // занулили слабый окончательно else begin e0^[i]:=0;e0^[i+1]:=0;e0^[i+2]:=0;end else begin e0^[i]:=255;e0^[i+1]:=255;e0^[i+2]:=255; end; end // 30 else if mga=60 then //(ang>22)and(ang<=67) =+45 begin mgg1:=g0^[i+3]; // направление / mga1:=a0^[i+3]; if mga=mga1 then // если углы направления градиента совпали то выбираем наибольшее значение градиента if (mgg>mgg1)and(mgg>porog) then begin e0^[i]:=255;e0^[i+1]:=255;e0^[i+2]:=255; end // занулили слабый окончательно else begin e0^[i+0]:=0;e0^[i+1]:=0;e0^[i+2]:=0; end else begin e0^[i]:=255;e0^[i+1]:=255;e0^[i+2]:=255; end; end else if mga=90 then //(ang>67)and(ang<=115) =+90 begin mgg1:=g0^[i]; // направление | mga1:=a0^[i]; if mga=mga1 then // если углы направления градиента совпали то выбираем наибольшее значение градиента if(mgg>mgg1)and(mgg>porog) then begin e0^[i]:=255;e0^[i+1]:=255;e0^[i+2]:=255; end // занулили слабый окончательно else begin e0^[i]:=0;e0^[i+1]:=0;e0^[i+2]:=0; end else begin e0^[i]:=255;e0^[i+1]:=255;e0^[i+2]:=255; end; end else if mga=120 then //(ang>115)and(ang<=162) =+135 begin mgg1:=g0^[i-3]; // направление \ mga1:=a0^[i-3]; if mga=mga1 then // если углы направления градиента совпали то выбираем наибольшее значение градиента if (mgg>mgg1)and(mgg>porog) then begin e0^[i]:=255;e0^[i+1]:=255;e0^[i+2]:=255; end // занулили слабый окончательно else begin e0^[i]:=0;e0^[i+1]:=0;e0^[i+2]:=0; end else begin e0^[i]:=255;e0^[i+1]:=255;e0^[i+2]:=255; end; end Хелп. Могу конечно весть проект положить или екзешник, чтобы не собирать его... Разными пробами кода удавалось получить меньше шума и кое-что похожее на окружности но они были рваные - незамкнутые, в тругих вариантах кода получалось получить боле-менее результат но на переходах углов всегда дырки в контуре.. В картинках - картинка исходник, собель, углы, канни |