Bagaimana Mendeteksi Gradien dan Tepian pada Gambar?

17

Saya ingin dapat menemukan titik dalam gambar yang merupakan pusat dari gradien radial seperti yang ditunjukkan pada gambar kiri di bawah ini. Ada ide tentang bagaimana saya bisa menggunakan transformasi Hough atau metode visi komputer lainnya?

Terima kasih

masukkan deskripsi gambar di sini

contoh gambar pencarian:

masukkan deskripsi gambar di sini

waspinator
sumber
Pertanyaan bagus!
Spacey
Juga, lihatlah Roberts 'Cross: ( en.wikipedia.org/wiki/Roberts_Cross ) sebagai contoh cara untuk memperkirakan gradien.
Spacey
terlihat seperti operator sedan yang lebih kecil. Saya tidak yakin bagaimana menggunakannya untuk menemukan gradien radial
waspinator
@waspinator: apakah Anda sudah menjalankan operator sobel pada gambar Anda dan melihat hasilnya? Ini seperti 2D yang setara dengan mengambil turunan dari fungsi 1D, jadi harus melintasi 0 pada minimum lokal atau maksimum?
endolith
1
Untuk pendekatan sederhana seperti Hough yang mungkin berhasil Anda bisa mencoba ini: untuk setiap piksel gambar, hitung arah gradien dan render segmen garis pendek ke arah gradien mulai dari piksel ini menjadi akumulator. Poin tengah yang Anda cari harus menjadi puncak tertinggi di akumulator (dengan margin besar).
koletenbert

Jawaban:

7

Saya sedang bekerja di OpenV dan mencoba mencari puncak gradien yang dihasilkan oleh transformasi jarak. Saya menyadari bahwa menggunakan operasi morfologis (erosi / dilatasi) dalam gambar skala abu-abu sangat berguna dalam kasus ini. Jika Anda mengikis dilatasi gambar skala abu-abu, piksel apa pun akan mengambil nilai tetangga yang lebih rendah / tertinggi. Karena itu Anda dapat menemukan puncak intensitas dalam gradien dengan mengurangi gambar skala abu-abu dari gambar yang dilatasi / terkikis yang sama. Inilah hasil saya: masukkan deskripsi gambar di sini

Dan cara untuk melakukannya di OpenCV / Cpp:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

int main( int argc, char** argv ){

    cv::Mat objects, img ,peaks,BGR;
    std::vector<std::vector<cv::Point> > contours;
    /* Reads the image*/
    BGR=cv::imread(argv[1]);
    /* Converts it to Grayscale*/
    cv::cvtColor(BGR,img,CV_BGR2GRAY);
    /* Devine where are the objects*/
    cv::threshold(img,objects,0,255,cv::THRESH_BINARY);
    /* In order to find the local maxima, "distance"
     * is subtracted from the result of the dilatation of
     * "distance". All the peaks keep the save value */
    cv::dilate(img,peaks,cv::Mat(),cv::Point(-1,-1),3);
    cv::dilate(objects,objects,cv::Mat(),cv::Point(-1,-1),3);

    /* Now all the peaks should be exactely 0*/
    peaks=peaks-img;

    /* And the non-peaks 255*/
    cv::threshold(peaks,peaks,0,255,cv::THRESH_BINARY);
    peaks.convertTo(peaks,CV_8U);

    /* Only the zero values of "peaks" that are non-zero
     * in "objects" are the real peaks*/
    cv::bitwise_xor(peaks,objects,peaks);

    /* The peaks that are distant from less than
     * 2 pixels are merged by dilatation */
    cv::dilate(peaks,peaks,cv::Mat(),cv::Point(-1,-1),1);

    /* In order to map the peaks, findContours() is used.
     * The results are stored in "contours" */
    cv::findContours(peaks, contours, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
    /* just draw them and save the image */
    cv::drawContours(BGR,contours,-1,cv::Scalar(255,0,0),-1);
    cv::imwrite("result.png",BGR);

    return 1;
}
Quentin Geissmann
sumber
5

Inilah yang saya miliki sejauh ini. Cara saya mengisi ruang Hough saya jauh dari optimal. Saya cukup yakin ada beberapa vektorisasi yang bisa saya lakukan untuk membuatnya lebih cepat. Saya menggunakan Matlab R2011a. Gambar asli

Saran dihargai, Terima kasih.

masukkan deskripsi gambar di sini

clear all; clc; close all;

%% read in image and find gradient information
img = rgb2gray(imread('123.png'));
[rows, columns] = size(img);
[dx, dy] = gradient(double(img));
[x y] = meshgrid(1:columns, 1:rows);
u = dx;
v = dy;
imshow(img);
hold on
quiver(x, y, u, v)


%% create Hough space and populate
hough_space = zeros(size(img));

for i = 1:columns
  for j = 1:rows

    X1 = i;
    Y1 = j;
    X2 = round(i + dx(j,i));
    Y2 = round(j + dy(j,i));
    increment = 1;

    slope = (Y2 - Y1) / (X2 - X1);
    y_intercept = Y1 - slope * X1;

    X3 = X1 + 5;

    if X3 < columns && X3 > 1
      Y3 = slope * X3 + y_intercept;
      if Y3 < rows && Y3 > 1
        hough_space = func_Drawline(hough_space, Y1, X1, floor(Y3), floor(X3), increment);
      end
    end
  end
end

imtool(hough_space)

Saya memodifikasi fungsi garis gambar yang saya temukan di matlab pusat untuk peningkatan piksel dengan nilai alih-alih mengatur piksel ke nilai

function Img = func_DrawLine(Img, X0, Y0, X1, Y1, nG)
% Connect two pixels in an image with the desired graylevel
%
% Command line
% ------------
% result = func_DrawLine(Img, X1, Y1, X2, Y2)
% input:    Img : the original image.
%           (X1, Y1), (X2, Y2) : points to connect.
%           nG : the gray level of the line.
% output:   result
%
% Note
% ----
%   Img can be anything
%   (X1, Y1), (X2, Y2) should be NOT be OUT of the Img
%
%   The computation cost of this program is around half as Cubas's [1]
%   [1] As for Cubas's code, please refer  
%   http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=4177  
%
% Example
% -------
% result = func_DrawLine(zeros(5, 10), 2, 1, 5, 10, 1)
% result =
%      0     0     0     0     0     0     0     0     0     0
%      1     1     1     0     0     0     0     0     0     0
%      0     0     0     1     1     1     0     0     0     0
%      0     0     0     0     0     0     1     1     1     0
%      0     0     0     0     0     0     0     0     0     1
%
%
% Jing Tian Oct. 31 2000
% [email protected]
% This program is written in Oct.2000 during my postgraduate in 
% GuangZhou, P. R. China.
% Version 1.0

Img(X0, Y0) = Img(X0, Y0) + nG;
Img(X1, Y1) = Img(X1, Y1) + nG;
if abs(X1 - X0) <= abs(Y1 - Y0)
   if Y1 < Y0
      k = X1; X1 = X0; X0 = k;
      k = Y1; Y1 = Y0; Y0 = k;
   end
   if (X1 >= X0) & (Y1 >= Y0)
      dy = Y1-Y0; dx = X1-X0;
      p = 2*dx; n = 2*dy - 2*dx; tn = dy;
      while (Y0 < Y1)
         if tn >= 0
            tn = tn - p;
         else
            tn = tn + n; X0 = X0 + 1;
         end
         Y0 = Y0 + 1; Img(X0, Y0) = Img(X0, Y0) + nG;
      end
   else
      dy = Y1 - Y0; dx = X1 - X0;
      p = -2*dx; n = 2*dy + 2*dx; tn = dy;
      while (Y0 <= Y1)
         if tn >= 0
            tn = tn - p;
         else
            tn = tn + n; X0 = X0 - 1;
         end
         Y0 = Y0 + 1; Img(X0, Y0) = Img(X0, Y0) + nG;
      end
   end
else if X1 < X0
      k = X1; X1 = X0; X0 = k;
      k = Y1; Y1 = Y0; Y0 = k;
   end
   if (X1 >= X0) & (Y1 >= Y0)
      dy = Y1 - Y0; dx = X1 - X0;
      p = 2*dy; n = 2*dx-2*dy; tn = dx;
      while (X0 < X1)
         if tn >= 0
            tn = tn - p;
         else
            tn = tn + n; Y0 = Y0 + 1;
         end
         X0 = X0 + 1; Img(X0, Y0) = Img(X0, Y0) + nG;
      end
   else
      dy = Y1 - Y0; dx = X1 - X0;
      p = -2*dy; n = 2*dy + 2*dx; tn = dx;
      while (X0 < X1)
         if tn >= 0
            tn = tn - p;
         else
            tn = tn + n; Y0 = Y0 - 1;
         end
         X0 = X0 + 1; Img(X0, Y0) = Img(X0, Y0) + nG;
      end
   end
end
waspinator
sumber
Saya pikir saya akan menghubungkan karunia itu dengan jawaban Anda, karena tidak ada orang lain yang mau berkontribusi. Bukan yang saya inginkan, tetapi yang paling dekat dari 3. Apakah Anda lebih meningkatkan metode ini?
Kode Cape
1

Jalankan Histogram Gradien Berorientasi pada tambalan gambar - puncak pada masing-masing histogram akan memberi Anda arah dominan tambalan itu (seperti panah yang Anda perlihatkan).

Temukan di mana semua panah berpotongan - jika titik itu berada di dalam objek itu bisa menjadi pusat gradien radial.

Martin Thompson
sumber