Abhishek
Abhishek

Reputation: 680

Creating Your Own Linear Filter

I am new to Opencv C++. I am trying to convolve a mask with an image. For this I want to create my own mask so that I can use the filter2D array function to convolve my mask with the image. The mask which I want to create is:

char mask [3][3]=  {{-1,0,1},{-1,0,1},{-1,0,1}};

For this I have tried the code below(to generate this mask):-

Mat kernel(3,3, CV_8UC1, Scalar(-1,0,1)); 

i have printed the mask values as

std::cout << kernel;

but the answer which I am getting is 0, 0, 0; 0, 0, 0; 0, 0, 0

I am expecting the answer to be -1, 0, 1; -1, 0, 1; -1, 0, 1

I know I am making a mistake in writing the channels properly. Can anyone help me understand what does the channel(CV_8UC1.... ) means and how to correct it and get the proper output.

Upvotes: 4

Views: 694

Answers (2)

Kinght 金
Kinght 金

Reputation: 18341

You want to create a kernel with negative element for filter2D, then you should't use the data type of CV_8UC1. There is no negative value in unsigned type.

And Mat kernel(3,3, CV_8UC1, Scalar(-1,0,1)); means create a signal- channel-unsigned-char kernel. You set Scalar(-1,0,1) to kernel, then only the first element(that is double -1) is used, while saturate_cast<unchar>(-1) = 0.

Generally, use CV_32FC1 instead.


For example:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main(){
    float mask[9] = {-1,0,1, -1, 0, 1, -1,0,1};
    Mat kernel(3,3, CV_32FC1);
    memcpy(kernel.data, mask, sizeof(float)*9);
    cout << kernel<<endl;
}

The result:

[-1, 0, 1;
 -1, 0, 1;
 -1, 0, 1]

A similar question:

How to create cv::Mat from buffer (array of T* data) using a template function?

Upvotes: 1

janu777
janu777

Reputation: 1978

CV_8UC1 means 1 channel, 8 bit, uchar image.

Scalar is used to set the value of each channel, not each pixel/coordinate.

Ex 1:

Mat kernel(3,3, CV_8UC1, Scalar::all(0)) 

would mean creating a 3X3 matrix with 0s and since it is of type CV_8UC1, you can mention only one value, in this case 0.

EX 2:

Mat kernel(3,3, CV_8UC3, Scalar(0,0,255)) 

means creating a 3X3 matrix with 3 channels since the type is CV_8UC3 and setting channel 1 to 0, channel 2 to 0, channel 3 to 255.

Hence for your purpose to set row values, you cannot use scalar. Instead do this:

Mat C = (Mat_<double>(3,3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);

Check this for more information.

Hope this helps!

Upvotes: 3

Related Questions