Image Convolutions in OpenCV

Convolutions are a very important tool for anyone interested in signal processing. Image Convolutions is a simpler method to do convolutions on images. And they have a lot of uses too. So of course, OpenCV does have a way to do image convolutions easily and super efficiently!

OpenCV’s Convolution Function

The C++ convolution function

The one single function that does image convolutions in OpenCV is the Filter2D function. Here’s the syntax:

void filter2D(Mat src,
              Mat dst,
              int ddepth,
              Mat kernel,
              Point anchor,
              double delta,
              int borderType);

You’ll have to include the cv namespace for the above to work. You can do that with

using namespace cv;

Now for the parameters:

  • src: (input) This is the image that you want to convolve.
  • dst: (input) This image stores the final result of the convolution. It should be the same size and have the same number of channels as src. This can be the same as src (in place operation is supported).
  • ddepth: (input) This is the desired bit depth of the final result (8, 16, 32, etc). It it is negative, the depth is the same as the source image.
  • kernel: (input) The convolution kernel used to convolve the source image. This has to be a single channel, floating point matrix. If you want to apply different kernels to different channels, you need to split the channels, and convolve each of them them individually.
  • anchor: (input) The relative position of the anchor in the kernel matrix. If this is set to (-1,-1), the center of the kernel is used as the anchor point.
  • delta: (input) A value that is added to all pixels after convolution.
  • borderType: (input) Possible values for this include:
    • BORDER_REPLICATE
    • BORDER_CONSTANT
    • BORDER_REFLECT_101
    • BORDER_WARP
    • BORDER_TRANSPARENT
    • BORDER_DEFAULT (same as reflect)
    • BORDER_ISOLATED

Here’s some example code:

filter2D(img, imgFiltered, -1, kernelLoG, Point(-1,-1), 5.0, BORDER_REPLICATE);

The image img is filtered and stored in imgFiltered. The bit depth of imgFiltered will be the same as img (the -1). The convolution will be done using the matrix kernelLog whose anchor is at the center. Also, after the convolution is done, a value of 5.0 will be added to all pixels. The borders are taken care of by replicating pixels around the edges.

The C image convolution function

The C equivalent of the above function is:

cvFilter2D(IplImage* src,
           IplImage* dst,
           CvMat* kernel,
           CvPoint anchor);

Very similar to the C++ equivalent and a lot simpler too. It doesn’t have a lot of extra parameters.

  • src: (input) The image you want to convolve.
  • dst: (input) The image where the result of the convolution is stored
  • kernel: (input) The matrix used to convolve the image.
  • anchor: (input) The anchor point of the kernel. If this is (-1,-1) the center of the kernel matrix is used as the anchor.

Pixels “outside” the image are set to the value of the pixel nearest inside the image.

A few things to keep in mind

The filtering function actually calculates correlation. If you have a symmetrical convolution kernel, the mathematical expressions for correlation and convolution are the same.

If the kernel is not symmetric, you must flip the kernel and set the anchor point to (kernel.cols – anchor.x – 1, kernel.rows – anchor.y – 1). This will calculate the actual convolution.

Also, it isn’t always necessary that the filtering will happen on the image directly. If the convolution kernel is large enough, OpenCV will automatically switch to a discrete Fourier transform based algorithm for speedy execution.

Summary

You got to know how convolutions are done in OpenCV. You learned about the C++ function as well as the C function.

Back to top

8 Comments

  1. Jaisheel Mistry
    Posted March 7, 2011 at 7:45 pm | Permalink

    Hi I have been trying to replicate the convolution of two matrices as shown in http://www.songho.ca/dsp/convolution/convolution2d_example.html, using your suggestion of fliping the kernal and reseting the anchor point, I however fail to get the correct resultant matrix. Below please find the snippet of code used. can you please guide me where I have went wrong, I have a feeling its something to do with the anchor point.

        Mat A=Mat(3,3,CV_32FC1);
        Mat B=Mat(3,3,CV_32FC1);
        Mat C=Mat(3,3,CV_32FC1);
     
        A.at(0,0)=1;
        A.at(0,1)=2;
        A.at(0,2)=3;
        A.at(1,0)=4;
        A.at(1,1)=5;
        A.at(1,2)=6;
        A.at(2,0)=7;
        A.at(2,1)=8;
        A.at(2,2)=9;
     
     
        B.at(0,0)=-1;
        B.at(0,1)=-2;
        B.at(0,2)=-1;
        B.at(1,0)=0;
        B.at(1,1)=0;
        B.at(1,2)=0;
        B.at(2,0)=1;
        B.at(2,1)=2;
        B.at(2,2)=1;
     
        Mat kernel;
        flip(B,kernel,-1);
     
        Point anchor=Point(1,1);//set to the middle of the kernal
     
        filter2D(A,C,-1,kernel,Point(kernel.cols-anchor.x-1,kernel.rows-anchor.y-1),0,BORDER_TRANSPARENT);
    • Posted March 11, 2011 at 7:43 pm | Permalink

      I just checked. It does work. Instead of BORDER_TRANSPARENT, set it to BORDER_CONSTANT. This makes the “nonexistent” elements equal to 0. Otherwise, OpenCV interpolates those nonexistent elements.

  2. Jaisheel Mistry
    Posted March 11, 2011 at 8:48 pm | Permalink

    thats weird I get the c matrix to be
    c= 0 0 0
    -24 -24 -24
    0 0 0

    instead of
    c=
    -13 -20 -17
    -18 -24 -18
    13 20 17

  3. Jaisheel Mistry
    Posted March 11, 2011 at 9:31 pm | Permalink

    yes

    • Posted March 11, 2011 at 9:33 pm | Permalink

      Do you use the correct instructions to read values from the matrix? Try ((float*)(C.data))[0]

  4. Jaisheel Mistry
    Posted March 11, 2011 at 9:41 pm | Permalink

    I use C.at(i,j) when iterating through C. My issue is that I am getting the correct C matrix of
    c=
    0 0 0
    -24 -24 -24
    0 0 0

    instead of
    c=
    -13 -20 -17
    -18 -24 -18
    13 20 17

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">