Làm thế nào để phát hiện học sinh và các cạnh trong hình ảnh?


17

Tôi muốn có thể tìm thấy các điểm trong hình ảnh là tâm của một gradient xuyên tâm giống như điểm được hiển thị trong hình bên trái. Bất kỳ ý tưởng nào về cách tôi có thể sử dụng một biến đổi Hough hoặc một số phương pháp thị giác máy tính khác?

Cảm ơn

nhập mô tả hình ảnh ở đây

hình ảnh tìm kiếm ví dụ:

nhập mô tả hình ảnh ở đây


Câu hỏi tuyệt vời!
Spacey

Ngoài ra, hãy xem Cross của Roberts: ( en.wikipedia.org/wiki/Roberts_Cross ) như một ví dụ về cách ước tính độ dốc.
Spacey

trông giống như một toán tử sobel nhỏ hơn. Tôi không chắc chắn làm thế nào để sử dụng điều đó để tìm một gradient xuyên tâm
waspinator

@waspinator: bạn đã chạy một toán tử sobel trên hình ảnh của mình và xem kết quả đầu ra chưa? Nó giống như 2D tương đương với việc lấy đạo hàm của hàm 1D, vì vậy nó nên vượt 0 ở cực tiểu hoặc cực đại cục bộ?
endolith

1
Đối với cách tiếp cận đơn giản giống như Hough có thể sẽ hiệu quả, bạn có thể thử điều này: với mỗi pixel của hình ảnh, hãy tính hướng dốc và hiển thị một đoạn đường ngắn theo hướng của gradient bắt đầu từ pixel này thành một bộ tích lũy. Các điểm trung tâm mà bạn đang tìm kiếm phải là các đỉnh cao nhất trong bộ tích lũy (bằng một lề lớn).
koletenbert

Câu trả lời:


7

Tôi đã làm việc trong opencv và cố gắng tìm đỉnh của một gradient được tạo bởi biến đổi khoảng cách. Tôi nhận ra rằng sử dụng các hoạt động hình thái (xói mòn / giãn nở) trong các hình ảnh màu xám là rất hữu ích trong trường hợp này. Nếu bạn làm xói mòn hình ảnh tỷ lệ xám, bất kỳ pixel nào cũng sẽ lấy giá trị của hàng xóm thấp hơn / cao nhất. Do đó, bạn có thể tìm thấy các cường độ cực đại theo độ dốc bằng cách trừ hình ảnh tỷ lệ xám khỏi cùng một hình ảnh bị giãn / bị xói mòn. Đây là kết quả của tôi: nhập mô tả hình ảnh ở đây

Và một cách để làm điều đó trong 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;
}

5

Đây là những gì tôi có cho đến nay. Cách tôi cư trú không gian Hough của tôi là xa tối ưu. Tôi khá chắc chắn rằng có một số vector hóa tôi có thể làm để làm cho nó nhanh hơn. Tôi đang sử dụng Matlab R2011a. Ảnh gốc

Gợi ý được đánh giá cao, Cảm ơn bạn.

nhập mô tả hình ảnh ở đây

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)

Tôi đã sửa đổi một hàm vẽ đường mà tôi tìm thấy trên trung tâm MATLAB để tăng từng pixel theo một giá trị thay vì đặt pixel thành một giá trị

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
% scuteejtian@hotmail.com
% 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

Tôi nghĩ rằng tôi sẽ gán tiền thưởng cho câu trả lời của bạn, vì không ai khác bận tâm đóng góp. Đó không phải là chính xác những gì tôi muốn nhưng nó là gần nhất trong số 3. Bạn đã cải thiện hơn nữa phương pháp này?
Mã Cape

1

Chạy một biểu đồ của các hướng được định hướng trên các bản vá của hình ảnh - đỉnh trong mỗi biểu đồ đó sẽ cho bạn hướng chủ đạo của bản vá đó (giống như các mũi tên bạn hiển thị).

Tìm nơi tất cả các mũi tên giao nhau - nếu điểm đó nằm trong đối tượng, nó có thể là tâm của một gradient xuyên tâm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.