Comment détecter les dégradés et les bords dans les images?

17

Je veux pouvoir trouver des points dans les images qui sont au centre d'un dégradé radial comme celui montré dans l'image de gauche ci-dessous. Avez-vous des idées sur la façon d'utiliser une transformation de Hough ou une autre méthode de vision par ordinateur?

Merci

entrez la description de l'image ici

exemple d'image de recherche:

entrez la description de l'image ici

waspinator
la source
Grande question!
Spacey
Jetez également un œil à Roberts 'Cross: ( en.wikipedia.org/wiki/Roberts_Cross ) comme exemple de méthode d'estimation des gradients.
Spacey
ressemble à un petit opérateur sobel. Je ne sais pas comment l'utiliser pour trouver un gradient radial
waspinator
@waspinator: bien avez-vous exécuté un opérateur sobel sur votre image et regardé la sortie? C'est comme l'équivalent 2D de prendre la dérivée d'une fonction 1D, donc elle devrait croiser 0 aux minima ou maxima locaux?
endolith
1
Pour une approche simple de type Hough qui fonctionnerait probablement, vous pouvez essayer ceci: pour chaque pixel de l'image, calculez la direction du gradient et restituez un segment de ligne court dans la direction du gradient commençant à ce pixel dans un accumulateur. Les points centraux que vous recherchez doivent être les pics les plus élevés de l'accumulateur (par une grande marge).
koletenbert

Réponses:

7

Je travaillais en opencv et essayais de trouver le pic d'un gradient généré par la transformation de distance. J'ai réalisé que l'utilisation d'opérations morphologiques (érosion / dilatation) dans des images à échelle de gris était très utile dans ce cas. Si vous érode dilatez une image en niveaux de gris, n'importe quel pixel va prendre la valeur du voisin inférieur / supérieur. Vous pouvez donc trouver des pics d'intensité dans les gradients en soustrayant l'image en niveaux de gris de la même image dilatée / érodée. Voici mon résultat: entrez la description de l'image ici

Et une façon de le faire dans 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
la source
5

Voici ce que j'ai jusqu'à présent. La façon dont je remplis mon espace Hough est loin d'être optimale. Je suis sûr que je peux faire de la vectorisation pour l'accélérer. J'utilise Matlab R2011a. Image originale

Les suggestions sont appréciées, merci.

entrez la description de l'image ici

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)

J'ai modifié une fonction de ligne de dessin que j'ai trouvée sur matlab central pour incrémenter d'un pixel d'une valeur au lieu de définir un pixel sur une valeur

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
la source
Je pense que j'attribuerai la prime à votre réponse, car personne d'autre n'a pris la peine de contribuer. Ce n'est pas exactement ce que je veux mais c'est le plus proche des 3. Avez-vous encore amélioré cette méthode?
Cape Code
1

Exécutez un histogramme de dégradés orientés sur les patchs de l'image - le pic de chacun de ces histogrammes vous donnera la direction dominante de ce patch (comme les flèches que vous montrez).

Trouvez où toutes ces flèches se croisent - si ce point est à l'intérieur de l'objet, il pourrait être le centre d'un dégradé radial.

Martin Thompson
la source