Reputation: 55
I need some help to figure this problem what i have right now. I have 3 images that are the same only the the different things, is that they represent Blue, Green and Red. I need to combine them and get a colored image back. I am using opencv and c++, but now i have this problem that i can't figure it out.
NEEDED: working on edge detection.
---- Update ---- I wrote some new code
Sobel(img_r, x, CV_16S, 1, 0);
Sobel(img_r, y, CV_16S, 0, 1);
//Compute the L1 norm
sobel_L1_norm = abs(x)+abs(y);
//Find Sobel max value
minMaxLoc(sobel_L1_norm, &min, &max);
sobel_L1_norm.convertTo(sobel_image, CV_32F, 255.0/(max - min), -min * 255.0/(max - min));
threshold(sobel_image, edgeThreshold, min, 255, THRESH_BINARY);
edgeThreshold.copyTo(img_r_edge);
I get this result bad example
But it should be like this. correct one
---- FULL CODE -----
Mat img_r = imread(input_path + "/01.png", CV_LOAD_IMAGE_GRAYSCALE);
Mat img_g = imread(input_path + "/02.png", CV_LOAD_IMAGE_GRAYSCALE);
Mat img_b = imread(input_path + "/03.png", CV_LOAD_IMAGE_GRAYSCALE);
// Edge Images
Mat img_r_edge = Mat::zeros(img_r.size(), CV_8UC1);
Mat img_g_edge = Mat::zeros(img_g.size(), CV_8UC1);
Mat img_b_edge = Mat::zeros(img_b.size(), CV_8UC1);
std::cout << "Step 1 - calculating edge images... ";
// TODO: 1) Calculate the 1st Sobel derivative once in x and once in y direction and combine these two
// (for every channel).
Mat x;
Mat y;
Mat abs_x;
Mat abs_y;
Mat sobel_L1_norm;
Mat sobel_image;
Mat edgeThreshold;
double min, max; //Finding min and max Sobel valuye;
//---------------------------------------------------
Sobel(img_r, x, CV_16S, 1, 0);
Sobel(img_r, y, CV_16S, 0, 1);
//Compute the L1 norm
sobel_L1_norm = abs(x)+abs(y);
//Find Sobel max value
minMaxLoc(sobel_L1_norm, &min, &max);
sobel_L1_norm.convertTo(sobel_image, CV_32F, 255.0/(max - min), -min * 255.0/(max - min));
threshold(sobel_image, edgeThreshold, min, 255, THRESH_BINARY);
edgeThreshold.copyTo(img_r_edge);
//----------------------------------------------------
// 2) Normalize every gradient image and convert the results to CV_8UC1.
// 3) Threshold the retrieved (normalized) gradient images using the parameter "edgeThreshold".
// 4) Save the results in the cv::Mats below.
imwrite(out_r_edge_filename, sobel);
imwrite(out_g_edge_filename, img_g_edge);
imwrite(out_b_edge_filename, img_b_edge);
Upvotes: 1
Views: 1460
Reputation: 41765
You are thresholding your sobel_image
with threshold min
.
However min
will (almost) always be 0
, since it's the minimum value of the sobel_L1_norm
image. Note that a pixel with no gradient will have a value of 0
in sobel_L1_norm
.
The solution to this is to choose a meaningful value for the threshold. Since you normalize the values to be in the range [0, 255]
, you can pick a value in that range (greater than 0).
If you normalize with values in [0,1]
, pick a value in this interval.
You can use normalize(..., NORM_MINMAX)
instead of finding the maximum and rescaling.
Also take care that edgeThreshold
will be a matrix of type CV_32F
after the call to threshold
, so it will be also img_r_edge
. To save the image correcly with imwrite
, wither use CV_32F
images in range [0,1]
, or CV_8U
images in range [0,255]. So you need either to rescale img_r_edge
in range [0,1]
, or convert it to CV_8U
.
You're mixing a lot of OpenCV types here. It's usually easier to use Mat_<Tp>
to know exactly the type.
You can always work with CV_32F
images, with range in [0,1].
Code that will produce correct output, with suggested modifications:
#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
Mat3b img = imread(path_to_color_image");
vector<Mat1b> planes;
split(img, planes);
Mat1b img_r = planes[2].clone();
Mat1b img_g = planes[1].clone();
Mat1b img_b = planes[0].clone();
// Edge Images
Mat1b img_r_edge;
Mat1b img_g_edge;
Mat1b img_b_edge;
// TODO: 1) Calculate the 1st Sobel derivative once in x and once in y direction and combine these two
// (for every channel).
Mat1f dx, dy;
Mat1f sobel_L1_norm;
Mat1f sobel_image;
Mat1f edgeThreshold;
double min, max; //Finding min and max Sobel valuye;
//---------------------------------------------------
Sobel(img_r, dx, CV_32F, 1, 0);
Sobel(img_r, dy, CV_32F, 0, 1);
//Compute the L1 norm
sobel_L1_norm = abs(dx) + abs(dy); // Type
// Normalize
normalize(sobel_L1_norm, sobel_image, 0, 1, NORM_MINMAX);
// Use a value different from 'min', which will (almost always) be 0.
double thresh = 0.5;
threshold(sobel_image, edgeThreshold, thresh, 255, THRESH_BINARY);
edgeThreshold.convertTo(img_r_edge, CV_8U);
imwrite("img_r_edge.png", img_r_edge);
return 0;
}
Upvotes: 1