6

Some details about my problem:

I'm trying to realize corner detector in openCV (another algorithm, that are built-in: Canny, Harris, etc).

I've got a matrix filled with the response values. The biggest response value is - the biggest probability of corner detected is.

I have a problem, that in neighborhood of a point there are few corners detected (but there is only one). I need to reduce number of false-detected corners.

Exact problem:

I need to walk through the matrix with a kernel, calculate maximum value of every kernel, leave max value, but others values in kernel make equal zero.

Are there build-in openCV functions to do this?

Rui Marques
  • 8,567
  • 3
  • 60
  • 91
Larry Foobar
  • 11,092
  • 15
  • 56
  • 89
  • Aren't you just looking for the local maxima? Like here: http://stackoverflow.com/questions/5550290/find-local-maxima-in-grayscale-image-using-opencv – Steve Heim May 25 '12 at 08:51
  • 1
    I don't need just local maximums in every kernel, but I need such a filter, when on every step only local maximum is remained in kernel, other values are zero – Larry Foobar May 25 '12 at 09:10
  • Not sure I understand what you mean, but in anycase, restricting this to a kernel, (or a ROI, and moving this ROI around in the image) using MinMaxLoc should work no? Like in their comment. – Steve Heim May 25 '12 at 09:36
  • 1
    Hm..but yes, you are right. I can loop through image with a kernel, and calculate MinMaxLoc. It returns not only value but and position of max value too. Than I make all elements in kernel equal zero, except max... I had this idea first time, but I thought may be openCV has easier built-in abilities to do this. – Larry Foobar May 25 '12 at 15:21

3 Answers3

19

This is how I would do it:

  1. Create a kernel, it defines a pixels neighbourhood.
  2. Create a new image by dilating your image using this kernel. This dilated image contains the maximum neighbourhood value for every point.
  3. Do an equality comparison between these two arrays. Wherever they are equal is a valid neighbourhood maximum, and is set to 255 in the comparison array.
  4. Multiply the comparison array, and the original array together (scaling appropriately).
  5. This is your final array, containing only neighbourhood maxima.

This is illustrated by these zoomed in images:

9 pixel by 9 pixel original image:

enter image description here

After processing with a 5 by 5 pixel kernel, only the local neighbourhood maxima remain (ie. maxima seperated by more than 2 pixels from a pixel with a greater value):

enter image description here

There is one caveat. If two nearby maxima have the same value then they will both be present in the final image.

Here is some Python code that does it, it should be very easy to convert to c++:

import cv

im = cv.LoadImage('fish2.png',cv.CV_LOAD_IMAGE_GRAYSCALE)
maxed = cv.CreateImage((im.width, im.height), cv.IPL_DEPTH_8U, 1)
comp = cv.CreateImage((im.width, im.height), cv.IPL_DEPTH_8U, 1)
#Create a 5*5 kernel anchored at 2,2
kernel = cv.CreateStructuringElementEx(5, 5, 2, 2, cv.CV_SHAPE_RECT)

cv.Dilate(im, maxed, element=kernel, iterations=1)
cv.Cmp(im, maxed, comp, cv.CV_CMP_EQ)
cv.Mul(im, comp, im, 1/255.0)

cv.ShowImage("local max only", im)
cv.WaitKey(0)

I didn't realise until now, but this is what @sansuiso suggested in his/her answer.

This is possibly better illustrated with this image, before:

enter image description here

after processing with a 5 by 5 kernel:

enter image description here

solid regions are due to the shared local maxima values.

fraxel
  • 34,470
  • 11
  • 98
  • 102
  • 1
    Thank you. Yes, I see, this is realization of extended @sansuiso's idea. – Larry Foobar May 25 '12 at 16:45
  • @Innuendo - yeah, its funny, I didnt read their answer until I was posting, it made me smile ;) – fraxel May 25 '12 at 16:51
  • @fraxel, I noticed your answer only after I answered a related question :) In my answer I suggest how to deal with pixels with equal values (plateaus). http://stackoverflow.com/a/21023493 – killogre Jan 09 '14 at 14:59
3

I would suggest an original 2-step procedure (there may exist more efficient approaches), that uses opencv built-in functions :

  1. Step 1 : morphological dilation with a square kernel (corresponding to your neighborhood). This step gives you another image, after replacing each pixel value by the maximum value inside the kernel.

  2. Step 2 : test if the cornerness value of each pixel of the original response image is equal to the max value given by the dilation step. If not, then obviously there exists a better corner in the neighborhood.

sansuiso
  • 9,259
  • 1
  • 40
  • 58
2

If you are looking for some built-in functionality, FilterEngine will help you make a custom filter (kernel).

http://docs.opencv.org/modules/imgproc/doc/filtering.html#filterengine

Also, I would recommend some kind of noise reduction, usually blur, before all processing. That is unless you really want the image raw.

Rui Marques
  • 8,567
  • 3
  • 60
  • 91