OpenCV filter2D negative values in C++ - c++

I'm trying to implement Histogram of Oriented Gradients on some video frames in C++. I used filter2D to convolute the frame image yet it seems that the resulting values are floored at 0. How do I get filter2D to give negative values as well?
Here's a snippet of code:
// Function that gets the histogram of gradients for a single video file
int HOG(string filename)
{
static int frames_read = 0;
VideoCapture cap(filename);
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat image;
namedWindow(filename,1);
// Read through frames of video
for(;;)
{
Mat frame;
float histogram[NUM_BINS * SPACIAL_X * SPACIAL_Y] = {0};
cap >> frame; // Get a new frame from camera
if(frame.empty())
break;
cvtColor(frame, image, CV_BGR2GRAY);
// Set up gradient kernels
float kernelX[9] = {0, 0, 0, -1.0, 0, 1.0, 0, 0, 0};
float kernelY[9] = {0, -1.0, 0, 0, 0, 0, 0, 1.0, 0};
Mat filterX(3, 3, CV_32F, kernelX);
Mat filterY(3, 3, CV_32F, kernelY);
Mat gradientX;
Mat gradientY;
// Apply gradients
filter2D(image, gradientX, CV_32F, filterX, Point (-1, 1), 0, BORDER_DEFAULT);
filter2D(image, gradientY, CV_32F, filterY, Point (-1, 1), 0, BORDER_DEFAULT);
}
}

Your code seems to be OK, and should generate positive results as well as negatives. How are you checking that there no negative results? Maybe you are converting floating point images to gray level (i.e. unsigned char), this indeed will crop all negative results.
It is easier to get same results by using Sobel function, that is dedicated to calculation of gradients in image:
Sobel(image, gradientX, CV_32F, 1, 0, 1);
Sobel(image, gradientY, CV_32F, 0, 1, 1);

Related

OpenCv overlay two Mat (drawings not images) with transparency

Hi what I have is a couple of Mat that I want to overlay (in a custom order). The Mat holdes some opencv polygons (which means a lot transparency). This Mat I need to overlay/merge. But not with the classical alpha blending more like with a 100% opacity but with transparency.
This is a simple sample code of what I want to merge.
Mat m1, m2;
m1.create(Point{ 100,100 }, CV_8UC4);
m2.create(Point{ 100,100 }, CV_8UC4);
cv::polylines(m1, std::vector<Point>{ Point{ 2,20 },Point{ 20,40 } }, true, Scalar(6, 6, 255));
cv::polylines(m2, std::vector<Point>{Point{ 100,100 }, Point{ 0,0 } }, true, Scalar(192, 112, 0));
Please note, that I cannot draw the polygons directly in one Mat due to various reasons.
I thought that maybe m1.copyTo(m2); will work, but its overwriting everything (incl. the black background)
Any idea how to get it merged/overlayed without the background? May I construct the mat's wrong?
I suspect you've had a problem looking for black in those images, as they were not initialized (it became apparent in debug mode). If we start with a zeroed out matrix, and draw using a 4-channel colour, so that the lines are visible, we get inputs such as this:
Input 1:
Input 2:
Now, we can use inRange to find all pixels set to (0,0,0,0). Since we want a mask of all non-black pixels, we just invert it by subtracting from 255. (i.e. mask = 255 - mask)
Mask:
Finally, use the mask as the second parameter of copyTo.
Result:
Code:
#include <opencv2/opencv.hpp>
int main()
{
cv::Mat m1(100, 100, CV_8UC4, cv::Scalar(0, 0, 0, 0));
cv::Mat m2(100, 100, CV_8UC4, cv::Scalar(0, 0, 0, 0));
cv::polylines(m1
, std::vector<cv::Point>{cv::Point{2, 20}, cv::Point{20, 40}}
, true, cv::Scalar(6, 6, 255, 255));
cv::polylines(m2
, std::vector<cv::Point>{cv::Point{100, 100}, cv::Point{0, 0}}
, true, cv::Scalar(192, 112, 0, 255));
cv::Mat mask;
cv::inRange(m2, cv::Scalar(0, 0, 0, 0), cv::Scalar(0, 0, 0, 0), mask);
mask = 255 - mask; // invert the mask
cv::Mat result(m1.clone());
m2.copyTo(result, mask);
cv::imwrite("transp_in_1.png", m1);
cv::imwrite("transp_in_2.png", m2);
cv::imwrite("transp_mask.png", mask);
cv::imwrite("transp_res.png", result);
return 0;
}
Instead of inverting the mask, you can invert the direction in which you copy. (i.e. overwrite everything black in m2 with stuff from m1)
cv::Mat mask;
cv::inRange(m2, cv::Scalar(0, 0, 0, 0), cv::Scalar(0, 0, 0, 0), mask);
cv::Mat result(m2.clone());
m1.copyTo(result, mask);

How to apply discrete Green's theorem to an image using the library Opencv?

I'm trying to implement the core detection algorithm on fingerprint from the paper "Singular Point Detection in Fingerprint Image".
1) I have defined the direction field from part 2 (original and Theta, W=2x2)
2) The next step is to find the gradient of field orientation (over x and y respectively):
Mat Jx, Jy;
Sobel(theta, Jx, CV_32F, 1, 0, 3, 1, 0, BORDER_DEFAULT);
Sobel(theta, Jy, CV_32F, 0, 1, 3, 1, 0, BORDER_DEFAULT);
3) Apply next formula to image (disctete Green's theoreme):
I do so, but I think it's wrong:
Mat Jx_dy, Jy_dx;
Sobel(Jy, Jy_dx, CV_32F, 1, 0, 3, 1, 0, BORDER_DEFAULT);
Sobel(Jx, Jx_dy, CV_32F, 0, 1, 3, 1, 0, BORDER_DEFAULT);
Mat G, _G;
cv::subtract(Jy_dx, Jx_dy, _G);
integral(_G,G);
imshow("Jy_dx - Jx_dy", _G); //totally black image
How to apply this formula on image?
Thanks.

Combining 2 images with transparent mask in opencv

What I'm basically trying to do is blur an image, and combine it back with the orignal, so that only certain areas in the original image are blurred (the face should be blurred).
My general idea was to mask the parts in the original Iwant to have blurred, then blur the original as a copy and "merge" them together again.
To a certain extend this also worked.
My images:
(1) Original
(2) Original with parts that should be blurred
(3) Blurred
My C++ code that creates these images:
int main(void) {
cv::Mat srcImage = cv::imread(path);
srcImage.convertTo(srcImage, CV_32FC3, 1.0/255.0);
Mat _mask;
Mat img_gray;
cv::Scalar white = cv::Scalar(255, 255, 255);
cv::Scalar black = cv::Scalar(0, 0, 0);
cv::cvtColor(srcImage, img_gray, cv::COLOR_BGR2GRAY);
img_gray.convertTo(_mask, CV_32FC1);
// face
cv::circle(_mask, cv::Point(430, 350), 200, black, -1, 8, 0);
// eyes
cv::circle(_mask, cv::Point(502, 260), 27, white, -1, 8, 0);
cv::circle(_mask, cv::Point(390, 260), 27, white, -1, 8, 0);
// mouth
cv::ellipse(_mask, cv::Point(440, 390), cv::Point(60, 25), 0, 0, 360, white, -1, 8, 0);
cv::threshold(1.0-_mask, _mask, 0.9, 1.0, cv::THRESH_BINARY_INV);
cv::GaussianBlur(_mask,_mask,Size(21,21),11.0);
cv::Mat res;
cv::Mat bg = Mat(srcImage.size(), CV_32FC3);
bg = cv::Scalar(1.0, 1.0 ,1.0);
vector<Mat> ch_img(3);
vector<Mat> ch_bg(3);
cv::split(srcImage, ch_img);
cv::split(bg, ch_bg);
ch_img[0] = ch_img[0].mul(_mask) + ch_bg[0].mul(1.0 - _mask);
ch_img[1] = ch_img[1].mul(_mask) + ch_bg[1].mul(1.0 - _mask);
ch_img[2] = ch_img[2].mul(_mask) + ch_bg[2].mul(1.0 - _mask);
cv::merge(ch_img, res);
cv::merge(ch_bg, bg);
// original but with white mask
res.convertTo(res, CV_8UC3, 255.0);
imwrite("original_with_mask.jpg", res);
// blur original image
cv::Mat blurredImage;
bilateralFilter(srcImage, blurredImage, 10, 20, 5);
GaussianBlur(srcImage, blurredImage, Size(19, 19), 0, 0);
blurredImage.convertTo(blurredImage, CV_8UC3, 255.0);
imwrite("blurred.jpg", blurredImage);
cv::Mat maskedImage;
maskedImage = Mat(srcImage.size(), CV_32FC3);
// now combine blurred image and original using mask
// this fails
cv::bitwise_and(blurredImage, _mask, maskedImage);
cv::imwrite("masked.jpg", maskedImage);
}
My problem is that cv::bitwise_and(blurredImage, _mask, maskedImage); fails with
OpenCV Error: Sizes of input arguments do not match (The operation is neither 'array op array' (where arrays have the same size and type), nor 'array op scalar', nor 'scalar op array') in binary_op
Probably because _mask is a single channel image and blurredImage and maskedImage are 3-channel images.
How can I combine the images I got so that the currently white areas in image (2) are blurred using a transparent mask with "soft" edges?
Instead of float conversion you can just use the linearcombination of byte channel values. See
int main(int argc, char* argv[])
{
cv::Mat srcImage = cv::imread("C:/StackOverflow/Input/transparentMaskInput.jpg");
// blur whole image
cv::Mat blurredImage;
//cv::bilateralFilter(srcImage, blurredImage, 10, 20, 5); // use EITHER bilateral OR Gaússian filter
cv::GaussianBlur(srcImage, blurredImage, cv::Size(19, 19), 0, 0);
// create mask
cv::Scalar white = cv::Scalar(255, 255, 255);
cv::Scalar black = cv::Scalar(0, 0, 0);
cv::Mat mask = cv::Mat::zeros(srcImage.size(), CV_8UC1);
// face
cv::circle(mask, cv::Point(430, 350), 200, black, -1, 8, 0);
// eyes
cv::circle(mask, cv::Point(502, 260), 27, white, -1, 8, 0);
cv::circle(mask, cv::Point(390, 260), 27, white, -1, 8, 0);
// mouth
cv::ellipse(mask, cv::Point(440, 390), cv::Point(60, 25), 0, 0, 360, white, -1, 8, 0);
cv::GaussianBlur(mask, mask, cv::Size(21, 21), 11.0);
// byte inversion:
cv::Mat invertedMask = 255 - mask; // instead of inversion you could just draw the "face" black on a white background!
cv::Mat outputImage = cv::Mat(srcImage.size(), srcImage.type());
// for each pixel, merge blurred and original image regarding the blur-mask
for (int y = 0; y < outputImage.rows; ++y)
for (int x = 0; x < outputImage.cols; ++x)
{
cv::Vec3b pixelOrig = srcImage.at<cv::Vec3b>(y, x);
cv::Vec3b pixelBlur = blurredImage.at<cv::Vec3b>(y, x);
float blurVal = invertedMask.at<unsigned char>(y, x)/255.0f; // value between 0 and 1: zero means 100% orig image, one means 100% blurry image
cv::Vec3b pixelOut = blurVal * pixelBlur + (1.0f - blurVal)* pixelOrig;
outputImage.at<cv::Vec3b>(y, x) = pixelOut;
}
cv::imshow("input", srcImage);
cv::imshow("blurred", blurredImage);
cv::imshow("mask", mask);
cv::imshow("inverted mask", invertedMask);
cv::imshow("output", outputImage);
return 0;
}
using this input image:
computing this blurred and mask:
resulting in this output, by computing (mask/255) * blur + (1-mask/255)*blur (linear combination):
I define a function to do alphaBlend for two images of CV_8UC3 with a mask of CV_8UC1 in OpenCV:
//! 2018.01.16 13:54:39 CST
//! 2018.01.16 14:43:26 CST
void alphaBlend(Mat& img1, Mat&img2, Mat& mask, Mat& blended){
// Blend img1 and img2 (of CV_8UC3) with mask (CV_8UC1)
assert(img1.size() == img2.size() && img1.size() == mask.size());
blended = cv::Mat(img1.size(), img1.type());
for (int y = 0; y < blended.rows; ++y){
for (int x = 0; x < blended.cols; ++x){
float alpha = mask.at<unsigned char>(y, x)/255.0f;
blended.at<cv::Vec3b>(y,x) = alpha*img1.at<cv::Vec3b>(y,x) + (1-alpha)*img2.at<cv::Vec3b>(y,x);
}
}
}
Then, it's easy to do alpha bend on the images, just call alphaBlend(...). Here is an example:
#include <opencv2/opencv.hpp>
using namespace cv;
//! 2018.01.16 13:54:39 CST
//! 2018.01.16 14:43:26 CST
void alphaBlend(Mat& img1, Mat&img2, Mat& mask, Mat& blended){
// Blend img1 and img2 (of CV_8UC3) with mask (CV_8UC1)
assert(img1.size() == img2.size() && img1.size() == mask.size());
blended = cv::Mat(img1.size(), img1.type());
for (int y = 0; y < blended.rows; ++y){
for (int x = 0; x < blended.cols; ++x){
float alpha = mask.at<unsigned char>(y, x)/255.0f;
blended.at<cv::Vec3b>(y,x) = alpha*img1.at<cv::Vec3b>(y,x) + (1-alpha)*img2.at<cv::Vec3b>(y,x);
}
}
}
Mat createMask(Size sz){
// create mask
cv::Mat mask = cv::Mat::zeros(sz, CV_8UC1);
// white and black
cv::Scalar white = cv::Scalar(255, 255, 255);
cv::Scalar black = cv::Scalar(0, 0, 0);
// face
cv::circle(mask, cv::Point(430, 350), 200, black, -1, 8, 0);
// eyes
cv::circle(mask, cv::Point(502, 260), 27, white, -1, 8, 0);
cv::circle(mask, cv::Point(390, 260), 27, white, -1, 8, 0);
// mouth
cv::ellipse(mask, cv::Point(440, 390), cv::Point(60, 25), 0, 0, 360, white, -1, 8, 0);
// Blur
cv::GaussianBlur(mask, mask, cv::Size(21, 21), 11.0);
return mask;
}
int main(){
cv::Mat img = cv::imread("img04.jpg");
// blur whole image
cv::Mat blured;
//cv::bilateralFilter(img, blured, 10, 20, 5); // use EITHER bilateral OR Gaússian filter
cv::GaussianBlur(img, blured, cv::Size(19, 19), 0, 0);
// Create the mask
Mat mask = createMask(img.size());
Mat mask_inv = 255 - mask;
// Alpha blend
Mat blended1, blended2;
alphaBlend(img, blured, mask, blended1);
alphaBlend(img, blured, mask_inv, blended2);
// Display
cv::imshow("source", img);
cv::imshow("blured", blured);
cv::imshow("mask", mask);
cv::imshow("mask_inv", mask_inv);
cv::imshow("blended1", blended1);
cv::imshow("blended2", blended2);
cv::waitKey();
return 0;
}
Source:
Blured:
Mask1:
AlphaBlend 1:
Mask 2:
AlphaBlend 2:
Some useful links:
Alpha Blending in OpenCV C++ : Combining 2 images with transparent mask in opencv
Alpha Blending in OpenCV Python:
Gradient mask blending in opencv python
Probably because _mask is a single channel image and blurredImage and
maskedImage are 3-channel images.
Put this before calling the cv::bitwise_and:
P.S if you do not want to alter your mask becuase you want to use it in another place just do it in a temporary variable:
cv::Mat _mask_temp;
cv::cvtColor(_mask,_mask_temp,cv::COLOR_GRAY2BGR);
cv::bitwise_and(blurredImage, _mask_temp, maskedImage);
_mask_temp.release(); // just in case you do not want it anymore to be in your memory(optional)
EDIT (another problem):
The mask is 32F while the image is 8U. So, you need this:
cv::cvtColor(_mask,_mask,cv::COLOR_GRAY2BGR);
_mask.convertTo(_mask, CV_8UC3);

OpenCV Watershed segmentation miss some objects

My code is the same as this tutorial.
When I see the result image after using cv::watershed(), there is a object(upper-right) that I want to find out, but it's missing.
There are indeed six marks in image after using cv::drawContours().
Is this normal because the inaccuracy of the watershed algorithm exist?
Here is part of my code:
Mat src = imread("result01.png");
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
Mat thresh;
threshold(gray, thresh, 0, 255, THRESH_BINARY | THRESH_OTSU);
// noise removal
Mat kernel = Mat::ones(3, 3, CV_8UC1);
Mat opening;
morphologyEx(thresh, opening, MORPH_OPEN, kernel, Point(-1, -1), 2);
// Perform the distance transform algorithm
Mat dist_transform;
distanceTransform(opening, dist_transform, CV_DIST_L2, 5);
// Normalize the distance image for range = {0.0, 1.0}
// so we can visualize and threshold it
normalize(dist_transform, dist_transform, 0, 1., NORM_MINMAX);
// Threshold to obtain the peaks
// This will be the markers for the foreground objects
Mat dist_thresh;
threshold(dist_transform, dist_thresh, 0.5, 1., CV_THRESH_BINARY);
Mat dist_8u;
dist_thresh.convertTo(dist_8u, CV_8U);
// Find total markers
vector<vector<Point> > contours;
findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
// Create the marker image for the watershed algorithm
Mat markers = Mat::zeros(dist_thresh.size(), CV_32SC1);
// Draw the foreground markers
for (size_t i = 0; i < contours.size(); i++)
drawContours(markers, contours, static_cast<int>(i), Scalar::all(static_cast<int>(i)+1), -1);
// Perform the watershed algorithm
watershed(src, markers);
Original image:
Result after watershed:
You can find original, intermediate and result image here:
Result images after specific process
In your example, what you consider background is given the same label (5) as the "missing" object.
You can easily adjust this by setting a label (>0) to background, too.
You can find what is for sure background dilating and negating the thresh image.
Then, when creating a marker, you define the labels as:
0: unknown
1: background
>1 : your objects
In your output image, markers will have:
-1 : the edges between objects
0: the background (as intended by watershed)
1: the background (as you defined)
>1 : your objects.
This code should help:
#include <opencv2\opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main()
{
Mat3b src = imread("path_to_image");
Mat1b gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
Mat1b thresh;
threshold(gray, thresh, 0, 255, THRESH_BINARY | THRESH_OTSU);
// noise removal
Mat1b kernel = getStructuringElement(MORPH_RECT, Size(3,3));
Mat1b opening;
morphologyEx(thresh, opening, MORPH_OPEN, kernel, Point(-1, -1), 2);
Mat1b kernelb = getStructuringElement(MORPH_RECT, Size(21, 21));
Mat1b background;
morphologyEx(thresh, background, MORPH_DILATE, kernelb);
background = ~background;
// Perform the distance transform algorithm
Mat1f dist_transform;
distanceTransform(opening, dist_transform, CV_DIST_L2, 5);
// Normalize the distance image for range = {0.0, 1.0}
// so we can visualize and threshold it
normalize(dist_transform, dist_transform, 0, 1., NORM_MINMAX);
// Threshold to obtain the peaks
// This will be the markers for the foreground objects
Mat1f dist_thresh;
threshold(dist_transform, dist_thresh, 0.5, 1., CV_THRESH_BINARY);
Mat1b dist_8u;
dist_thresh.convertTo(dist_8u, CV_8U);
// Find total markers
vector<vector<Point> > contours;
findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
// Create the marker image for the watershed algorithm
Mat1i markers(dist_thresh.rows, dist_thresh.cols, int(0));
// Background as 1
Mat1i one(markers.rows, markers.cols, int(1));
bitwise_or(one, markers, markers, background);
// Draw the foreground markers (from 2 up)
for (int i = 0; i < int(contours.size()); i++)
drawContours(markers, contours, i, Scalar(i+2), -1);
// Perform the watershed algorithm
Mat3b dbg;
cvtColor(opening, dbg, COLOR_GRAY2BGR);
watershed(dbg, markers);
Mat res;
markers.convertTo(res, CV_8U);
normalize(res, res, 0, 255, NORM_MINMAX);
return 0;
}
Result:
there is very little emgu cv data on watershed.
here is my translation to this problem using c#. i know it is not the right forum but this answer kips popping up so to all the searchers:
//Mat3b src = imread("path_to_image");
//cvtColor(src, gray, COLOR_BGR2GRAY);
Image<Gray, byte> gray = smallImage.Convert<Gray, byte>();
//threshold(gray, thresh, 0, 255, THRESH_BINARY | THRESH_OTSU);
Image<Gray, byte> thresh = gray.ThresholdBinaryInv(new Gray(55), new Gray(255));
// noise removal
Mat kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), new Point(-1, -1));
//Mat1b opening;
//morphologyEx(thresh, opening, MORPH_OPEN, kernel, Point(-1, -1), 2);
Image<Gray, byte> opening = thresh.MorphologyEx(MorphOp.Open, kernel, new Point(-1, -1), 2, BorderType.Default, new MCvScalar(255));
//Mat1b kernelb = getStructuringElement(MORPH_RECT, Size(21, 21));
Mat kernel1 = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), new Point(-1, -1));
//Mat1b background;
//morphologyEx(thresh, background, MORPH_DILATE, kernelb);
Image<Gray, byte> background = thresh.MorphologyEx(MorphOp.Dilate, kernel, new Point(-1, -1), 2, BorderType.Default, new MCvScalar(255));
background = ~background;
//// Perform the distance transform algorithm
//Mat1f dist_transform;
//distanceTransform(opening, dist_transform, CV_DIST_L2, 5);
Image<Gray, float> dist_transform = new Image<Gray, float>(opening.Width, opening.Height);
CvInvoke.DistanceTransform(opening, dist_transform, null, DistType.L2, 5);
//// Normalize the distance image for range = {0.0, 1.0}
//// so we can visualize and threshold it
//normalize(dist_transform, dist_transform, 0, 1., NORM_MINMAX);
CvInvoke.Normalize(dist_transform, dist_transform, 0, 1.0, NormType.MinMax, DepthType.Default);
//// Threshold to obtain the peaks
//// This will be the markers for the foreground objects
//Mat1f dist_thresh;
//threshold(dist_transform, dist_thresh, 0.5, 1., CV_THRESH_BINARY);
Image<Gray, float> dist_thresh = new Image<Gray, float>(opening.Width, opening.Height);
CvInvoke.Threshold(dist_transform, dist_thresh, 0.5, 1.0, ThresholdType.Binary);
//Mat1b dist_8u;
//dist_thresh.convertTo(dist_8u, CV_8U);
Image<Gray, Byte> dist_8u = dist_thresh.Convert<Gray, Byte>();
//// Find total markers
//vector<vector<Point>> contours;
//findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
CvInvoke.FindContours(dist_8u, contours, null, RetrType.External, ChainApproxMethod.ChainApproxSimple);
//// Create the marker image for the watershed algorithm
//Mat1i markers(dist_thresh.rows, dist_thresh.cols, int(0));
Image<Gray, int> markers = new Image<Gray, int>(dist_thresh.Width, dist_thresh.Height, new Gray(0));
//// Background as 1
//Mat1i one(markers.rows, markers.cols, int(1));
//bitwise_or(one, markers, markers, background);
Image<Gray, int> one = new Image<Gray, int>(markers.Cols, markers.Rows, new Gray(1));
CvInvoke.BitwiseOr(one, markers, markers, background);
//// Draw the foreground markers (from 2 up)
for (int i = 0; i < contours.Size; i++)
// drawContours(markers, contours, i, Scalar(i + 2), -1);
CvInvoke.DrawContours(markers, contours, i, new MCvScalar(i + 2));
//// Perform the watershed algorithm
//Mat3b dbg;
//cvtColor(opening, dbg, COLOR_GRAY2BGR);
//watershed(dbg, markers);
Image<Bgr, byte> dbg = new Image<Bgr, byte>(markers.Cols, markers.Rows);
CvInvoke.CvtColor(opening, dbg, ColorConversion.Gray2Bgr);
CvInvoke.Watershed(dbg, markers);
//Mat res;
//markers.convertTo(res, CV_8U);
//normalize(res, res, 0, 255, NORM_MINMAX);
CvInvoke.Normalize(markers, markers, 0, 255, NormType.MinMax);
//return 0;
to find light objects on dark background replace ThresholdBinaryInv with ThresholdBinary

How to extract Numerical gradient matrix from the image matrix in Opencv

i am searching a way to get Numerical gradient from the matrix. The same
function is implemented in matlab's default documentation.http://www.mathworks.com/help/techdoc/ref/gradient.html but i couldn't find any in opencv.
I want to port this to C++ using opencv.
should i use sobel for horizontal and vertical gradient or any
other function or way to do it???
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
/// Gradient X
Sobel( mat, grad_x, CV_32F, 1, 0, 3);
imshow("xx",grad_x);
convertScaleAbs( grad_x, abs_grad_x );
/// Gradient Y
Sobel( mat, grad_y, CV_32F, 0, 1, 3);
convertScaleAbs( grad_y, abs_grad_y );
/// Total Gradient (approximate)
Mat res;
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, res );
[EDIT]
solution
Mat grad_x,abs_grad_x,grad_y,abs_grad_y;
int type=CV_64F ;
Gradient.setTo(Scalar::all(0));
/// Gradient Y
Sobel( input, grad_x, type, 1, 0, 3);
convertScaleAbs(grad_x,abs_grad_x);
cv::accumulateSquare(abs_grad_x,Gradient);
/// Gradient Y
Sobel(input, grad_y, type, 0, 1, 3);
convertScaleAbs(grad_y,abs_grad_y);
cv::accumulateSquare(abs_grad_y,Gradient);
imshow("gradient Mag",Gradient);
You can find the gradient calculation here Just like you have said to calculate sobel gradients, the example does so.