opencv find homography using feature matching - c++

I am calculating homography with reference here.
http://docs.opencv.org/2.4/doc/tutorials/features2d/feature_homography/feature_homography.html
However, there is an error even though it is a reference code.
The min_dist value is always 0, so the size of good_matches is 0, in the code.
What is wrong and how can we solve it?
int main(int argc, char **argv)
{
cv::VideoCapture cam(0);
cv::Mat img(480, 640, CV_8UC3, cv::Scalar(0, 0, 0));
cv::Mat img2(480, 640, CV_8UC3, cv::Scalar(0, 0, 0));
cv::Ptr<cv::AKAZE> akaze = cv::AKAZE::create();
std::vector<cv::KeyPoint> kp;
cv::Mat descr;
while (1)
{
cam >> img;
cv::Mat aka;
akaze->detectAndCompute(img, cv::noArray(), kp, descr);
cv::drawKeypoints(img, kp, aka);
cv::imshow("AKAZE", aka);
if (cv::waitKey(10) == 's')
{
break;
}
kp.clear();
}
akaze.release();
std::vector<cv::KeyPoint> kp_query;
cv::Mat descr_query;
cv::Ptr<cv::AKAZE> akaze2 = cv::AKAZE::create();
while (1)
{
cv::Mat aka;
cam >> img2;
akaze2->detectAndCompute(img2, cv::noArray(), kp_query, descr_query);
cv::BFMatcher matcher(cv::NORM_HAMMING);
std::vector<cv::DMatch> matches;
matcher.match(descr_query, descr, matches);
double max_dist = 0, min_dist = 100.0;
for (int i = 0; i<descr_query.rows; i++)
{
double dist = matches[i].distance;
if (dist < min_dist) min_dist = dist;
if (dist > max_dist) max_dist = dist;
}
printf("-- Max dist : %f \n", max_dist);
printf("-- Min dist : %f \n", min_dist);
std::vector<cv::DMatch> good_matches;
for (int i = 0; i<descr_query.rows; i++)
{
if (matches[i].distance < 3 * min_dist)
good_matches.push_back(matches[i]);
}
std::vector<cv::Point2f> train, query;
for (int i = 0; i<good_matches.size(); i++)
{
train.push_back(kp[good_matches[i].queryIdx].pt);
query.push_back(kp_query[good_matches[i].trainIdx].pt);
}
cv::Mat output_mask;
cv::Mat H = cv::findHomography(train, query, CV_RANSAC, 3, output_mask);
cv::Mat m;
cv::drawMatches(img, kp, img2, kp_query, good_matches, m, cv::Scalar::all(-1), cv::Scalar::all(-1),
std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
cv::imshow("match", m);
cv::drawKeypoints(img2, kp_query, aka);
cv::waitKey(10);
kp_query.clear();
}
}

So far, I could't see any wrong procedure in your code, But you have 3 Channel 8-Bit Image there. Try to use a 1 Channel 8-Bit Image, because that is the format of the Images in your linked tutorial. So try changing cv::Mat img2(480, 640, CV_8UC3, cv::Scalar(0, 0, 0)); to cv::Mat img2(480, 640, CV_8UC1, cv::Scalar(0, 0, 0)); For both images. If this is not working for cam >> img then you have to try to convert image to CV_8UC1 after you read it from your cam.

Related

stitch two images in opencv C++

I want to make a musaic image by stitching some images.
I am doing this by sift features.
when I stitch the following two images :
img1
img2
I achieve this result. as you can see the images are not aligned completely and there is a gap between them. Can you tell me what is the problem and how can I solve it?
Here is my function that I used for stitching :
Mat StitchVertical(Mat& imGrayImg1, Mat& imGrayImg2)
{
Mat GrayImg1(imGrayImg1, Rect(0, 0, imGrayImg1.cols, imGrayImg1.rows)); // init roi
Mat GrayImg2(imGrayImg2, Rect(0, 0, imGrayImg2.cols, imGrayImg2.rows));
cvtColor(GrayImg1, GrayImg1, COLOR_BGR2GRAY);
cvtColor(GrayImg2, GrayImg2, COLOR_BGR2GRAY);
vector<cv::KeyPoint> keypointsImg1, keypointsImg2;
Mat descriptorImg1, descriptorImg2;
BFMatcher matcher;
vector<cv::DMatch> matches, good_matches;
cv::Ptr<cv::SIFT> sift = cv::SIFT::create();
int i, dist = 80;
sift->detectAndCompute(GrayImg1, cv::Mat(), keypointsImg1, descriptorImg1); /* get keypoints of ROI image */
sift->detectAndCompute(GrayImg2, cv::Mat(), keypointsImg2, descriptorImg2); /* get keypoints of the image */
matcher.match(descriptorImg1, descriptorImg2, matches); // Matching between descriptors
double max_dist = 0; double min_dist = 5000;
for (int i = 0; i < descriptorImg1.rows; i++)
{
double dist = matches[i].distance;
if (dist < min_dist) min_dist = dist;
if (dist > max_dist) max_dist = dist;
}
for (i = 0; i < descriptorImg1.rows; i++)
{
if (matches[i].distance < 3 * min_dist)
{
good_matches.push_back(matches[i]);
}
}
Mat img_matches;
// Draw match
drawMatches(imGrayImg1, keypointsImg1, imGrayImg2, keypointsImg2,
good_matches, img_matches, Scalar::all(-1),
Scalar::all(-1), vector<char>(),
DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
//imshow("matches", img_matches);
vector<Point2f> keypoints1, keypoints2;
for (i = 0; i < good_matches.size(); i++)
{
keypoints1.push_back(keypointsImg2[good_matches[i].trainIdx].pt);
keypoints2.push_back(keypointsImg1[good_matches[i].queryIdx].pt);
}
Mat H, H2;
H = findHomography(keypoints1, keypoints2, RANSAC);
H2 = findHomography(keypoints2, keypoints1, RANSAC);
Mat stitchedImage;
int mRows = imGrayImg2.cols;
if (imGrayImg1.cols > imGrayImg2.cols)
{
mRows = imGrayImg1.cols;
}
int count = 0;
for (int i = 0; i < keypoints2.size(); i++)
{
if (keypoints2[i].y >= imGrayImg2.rows / 3) { count++; }
}
int minx,miny;
if (count / float(keypoints2.size()) >= 0.5) // To be spliced imGrayImg2 The image is on the right
{
cout << "imGrayImg1 should left" << endl;
vector<Point2f>corners(4);
vector<Point2f>corners2(4);
corners[0] = Point(0, 0);
corners[1] = Point(0, imGrayImg2.rows);
corners[2] = Point(imGrayImg2.cols, imGrayImg2.rows);
corners[3] = Point(imGrayImg2.cols, 0);
stitchedImage = Mat::zeros( mRows, imGrayImg2.rows + imGrayImg1.rows, CV_8UC3);
warpPerspective(imGrayImg2, stitchedImage, H, Size(mRows, imGrayImg1.cols + imGrayImg2.cols));
perspectiveTransform(corners, corners2, H);
Mat half(stitchedImage, Rect(0, 0, imGrayImg1.cols, imGrayImg1.rows));
imGrayImg1.copyTo(half);
minx = stitchedImage.size().width;
miny = stitchedImage.size().height;
if ((int(corners2[2].x) - 10) < stitchedImage.size().width) {
minx = (int(corners2[2].x) - 10);
}
if ((int(corners2[2].y) - 10) < stitchedImage.size().height) {
miny = (int(corners2[2].y) - 10);
}
Rect crop_region(0, 0, minx, miny);
Mat cropped_image = stitchedImage(crop_region);
return cropped_image;
}
else
{
cout << "imGrayImg2 should be up" << endl;
stitchedImage = Mat::zeros(mRows, imGrayImg2.rows + imGrayImg1.rows, CV_8UC3);
warpPerspective(imGrayImg1, stitchedImage, H2, Size(mRows, imGrayImg1.cols + imGrayImg2.cols));
//imshow("temp", stitchedImage);
vector<Point2f>corners(4);
vector<Point2f>corners2(4);
corners[0] = Point(0, 0);
corners[1] = Point(0, imGrayImg1.rows);
corners[2] = Point(imGrayImg1.cols, imGrayImg1.rows);
corners[3] = Point(imGrayImg1.cols, 0);
cout << "second if in up and down" << endl;
perspectiveTransform(corners, corners2, H2); // Affine transformations correspond to endpoints
Mat half(stitchedImage, Rect(0, 0, imGrayImg2.cols, imGrayImg2.rows));
imGrayImg2.copyTo(half);
minx = stitchedImage.size().width;
miny = stitchedImage.size().height;
if ((int(corners2[2].x) - 10) < stitchedImage.size().width) {
minx = (int(corners2[2].x) - 10);
}
if ((int(corners2[2].y) - 10) < stitchedImage.size().height) {
miny = (int(corners2[2].y) - 10);
}
Rect crop_region(0, 0, minx, miny);
Mat cropped_image = stitchedImage(crop_region); return cropped_image;
}
imwrite("result.bmp", stitchedImage);
return stitchedImage;
}

Opencv linear gray value transformation

hey i want to do a linear gray transformation, so that i can change the contrast.
how i can get the maximum and minimum gray value ? and then i want to scale the Image that it has a limited contrast range of 100 to 150. I have searched like 2 hours but dont found something.
would be nice if someone could help
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
cv::Mat plotHistogram(cv::Mat &image, bool cumulative = true, int histSize = 256);
int main()
{
cv::Mat img = cv::imread(schrott.png"); // Read the file
if (img.empty()) // Check for invalid input
{
std::cout << "Could not open or find the frame" << std::endl;
return -1;
}
cv::Mat img_gray;
cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY); // In case img is colored
cv::namedWindow("Input Image", cv::WINDOW_AUTOSIZE); // Create a window for display.
cv::imshow("Input Image", img);
cv::Mat hist;
hist = plotHistogram(img_gray);
cv::namedWindow("Histogram", cv::WINDOW_NORMAL); // Create a window for display.
cv::imshow("Histogram", hist);
cv::waitKey(0);
}
cv::Mat plotHistogram(cv::Mat &image, bool cumulative, int histSize) {
// Create Image for Histogram
int hist_w = 1024; int hist_h = 800;
int bin_w = cvRound((double)hist_w / histSize);
cv::Mat histImage(hist_h, hist_w, CV_8UC1, Scalar(255, 255, 255));
if (image.channels() > 1) {
cerr << "plotHistogram: Please insert only gray images." << endl;
return histImage;
}
// Calculate Histogram
float range[] = { 0, 256 };
const float* histRange = { range };
cv::Mat hist;
calcHist(&image, 1, 0, Mat(), hist, 1, &histSize, &histRange);
if (cumulative) {
cv::Mat accumulatedHist = hist.clone();
for (int i = 1; i < histSize; i++) {
accumulatedHist.at<float>(i) += accumulatedHist.at<float>(i - 1);
}
hist = accumulatedHist;
}
// Normalize the result to [ 0, histImage.rows ]
normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
// Draw bars
for (int i = 1; i < histSize; i++) {
cv::rectangle(histImage, Point(bin_w * (i - 1), hist_h),
Point(bin_w * (i), hist_h - cvRound(hist.at<float>(i))),
Scalar(50, 50, 50), 1);
}
return histImage; // Not really call by value, as cv::Mat only saves a pointer to the image data
}
You can find minimum and maximum value with minMaxLoc
Mat image;
//read image;
double min, max;
minMaxLoc( image, &min, &max );
cout << "min : " << min << "max : " << max << endl;

OpenCv - Assertion failed in svm train

I can find why i this happening. I have 5 classes and made labels and trainData but it gives assertion failed. Why? Labels are 1x1x884 ( i tried 1x884x1 also, it is the same ), and fmat 1 x 884 x 680400 , all float32. Error is :
and code:
HOGDescriptor hog;
vector<vector< float>> features;
int labels[884] = {};
int brojac = 0;
cv::String path1("C:/Users/Kristina/Desktop/Kompjuterska vizija/PrviProjekat/PrviProjekat/Chihuahua/*.jpg"); //select only jpg
vector<cv::String> fn;
vector<cv::Mat> data;
cv::glob(path1, fn, true); // recurse
for (size_t k = 0; k<fn.size(); ++k)
{
cv::Mat im = cv::imread(fn[k]);
if (im.empty()) continue; //only proceed if sucsessful
// you probably want to do some preprocessing
cvtColor(im, im, CV_RGB2GRAY);
resize(im, im, Size(200, 200));//resize image
vector< float> descriptorsValues;
hog.compute(im, descriptorsValues);
features.push_back(descriptorsValues);
labels[brojac] = 1;
brojac++;
data.push_back(im);
}
cv::String path2("C:/Users/Kristina/Desktop/Kompjuterska vizija/PrviProjekat/PrviProjekat/ShihTzu/*.jpg"); //select only jpg
vector<cv::String> fn2;
vector<cv::Mat> data2;
cv::glob(path2, fn2, true); // recurse
for (size_t k = 0; k<fn2.size(); ++k)
{
cv::Mat im = cv::imread(fn2[k]);
vector< float> descriptorsValues;
if (im.empty()) continue; //only proceed if sucsessful
// you probably want to do some preprocessing
cvtColor(im, im, CV_RGB2GRAY);
resize(im, im, Size(200, 200));//resize image
hog.compute(im, descriptorsValues);
features.push_back(descriptorsValues);
labels[brojac] = 2;
brojac++;
data.push_back(im);
}
cv::String path3("C:/Users/Kristina/Desktop/Kompjuterska vizija/PrviProjekat/PrviProjekat/Yorkshireterrier/*.jpg"); //select only jpg
vector<cv::String> fn3;
vector<cv::Mat> data3;
cv::glob(path3, fn3, true); // recurse
for (size_t k = 0; k<fn3.size(); ++k)
{
vector< float> descriptorsValues;
cv::Mat im = cv::imread(fn3[k]);
if (im.empty()) continue; //only proceed if sucsessful
// you probably want to do some preprocessing
cvtColor(im, im, CV_RGB2GRAY);
resize(im, im, Size(200, 200));//resize image
hog.compute(im, descriptorsValues);
features.push_back(descriptorsValues);
labels[brojac] = 3;
brojac++;
data.push_back(im);
}
cv::String path4("C:/Users/Kristina/Desktop/Kompjuterska vizija/PrviProjekat/PrviProjekat/vizsla/*.jpg"); //select only jpg
vector<cv::String> fn4;
vector<cv::Mat> data4;
cv::glob(path4, fn4, true); // recurse
for (size_t k = 0; k<fn4.size(); ++k)
{
cv::Mat im = cv::imread(fn4[k]);
vector< float> descriptorsValues;
if (im.empty()) continue; //only proceed if sucsessful
// you probably want to do some preprocessing
cvtColor(im, im, CV_RGB2GRAY);
resize(im, im, Size(200, 200));//resize image
hog.compute(im, descriptorsValues);
features.push_back(descriptorsValues);
labels[brojac] = 4;
brojac++;
data.push_back(im);
}
cv::String path5("C:/Users/Kristina/Desktop/Kompjuterska vizija/PrviProjekat/PrviProjekat/pug/*.jpg"); //select only jpg
vector<cv::String> fn5;
vector<cv::Mat> data5;
cv::glob(path5, fn5, true); // recurse
for (size_t k = 0; k<fn5.size(); ++k)
{
cv::Mat im = cv::imread(fn5[k]);
vector< float> descriptorsValues;
if (im.empty()) continue; //only proceed if sucsessful
// you probably want to do some preprocessing
cvtColor(im, im, CV_RGB2GRAY);
resize(im, im, Size(200, 200));//resize image
hog.compute(im, descriptorsValues);
features.push_back(descriptorsValues);
labels[brojac] = 5;
brojac++;
data.push_back(im);
}
Mat labelsMat(884, 1, CV_32FC1, labels);
Mat fmat(features[0].size(), features.size(), CV_32FC1, features.data());
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
svm->train(fmat, ml::SampleTypes::ROW_SAMPLE, labelsMat);

Crop Triangle with opencv c++

User,
I want to crop that Triangle on the image and show it in another window with opencv c++. I know all three Coordinates.
Can anyone help me? I did not find any answer on the Internet about "triangle cropping". Thanks!
EDIT: The Problem here is that i cannot use ROI for cropping the Triangle. I have to copy just the triangle without any background or something around. Is it possible to create my own ROI by knowing the Coordinates of the triangle [p1(302,179), p2(329,178), p3(315,205)]?
cv::Mat inputImage = cv::imread("input.png");
if (inputImage.channels() > 1)
{
cv::cvtColor(inputImage, inputImage, CV_RGB2GRAY);
}
// replace these values with your actual coordinates
// I found these by first saving your provided image, then
// using Microsoft Paint
int x0 = 242;
int y0 = 164;
int x1 = 314;
int y1 = 38;
int x2 = 387;
int y2 = 164;
// then create a line masking using these three points
cv::Mat lineMask = cv::Mat::zeros(inputImage.size(), inputImage.type());
cv::line(lineMask, cv::Point(x0, y0), cv::Point(x1, y1), cv::Scalar(255, 255, 0), 1, 8, 0);
cv::line(lineMask, cv::Point(x0, y0), cv::Point(x2, y2), cv::Scalar(255, 255, 0), 1, 8, 0);
cv::line(lineMask, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(255, 255, 0), 1, 8, 0);
// perform contour detection on your line mask
cv::vector<cv::vector<cv::Point>> contours;
cv::vector<cv::Vec4i> hierarchy;
cv::findContours(lineMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
// calculate the distance to the contour
cv::Mat raw_dist(lineMask.size(), CV_32FC1);
for (int i = 0; i < lineMask.rows; i++)
{
for (int j = 0; j < lineMask.cols; j++)
{
raw_dist.at<float>(i, j) = cv::pointPolygonTest(contours[0], cv::Point2f(j, i), true);
}
}
double minVal; double maxVal;
cv::minMaxLoc(raw_dist, &minVal, &maxVal, 0, 0, cv::Mat());
minVal = std::abs(minVal);
maxVal = std::abs(maxVal);
// depicting the distances graphically
cv::Mat mask = cv::Mat::zeros(inputImage.size(), CV_8UC1);
for (int i = 0; i < mask.rows; i++)
{
for (int j = 0; j < mask.cols; j++)
{
if (raw_dist.at<float>(i, j) < 0)
{
mask.at<uchar>(i, j) = static_cast<uchar>(0);
continue;
}
mask.at<uchar>(i, j) = static_cast<uchar>(255);
}
}
// inverse the input image
cv::Mat invInput;
cv::bitwise_not(inputImage, invInput);
// then get only the region of your triangle
cv::Mat outputImage;
invInput.copyTo(outputImage, mask);
cv::bitwise_not(outputImage, outputImage);
// display for debugging purpose
cv::imshow("inputImage", inputImage);
cv::imshow("lineMask", lineMask);
cv::imshow("mask", mask);
cv::imshow("outputImage", outputImage);
cv::waitKey();
This is your inputImage:
This is your lineMask:
This is your created binary mask:
And this is your final outputImage:
References:
OpenCV draw line
OpenCV findContours
Point Polygon Test
you can do it by using mask as shown with the code below
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( int, char** argv )
{
Mat src = imread( argv[1] );
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY );
gray = gray < 127;
vector<vector<Point> > contours;
findContours(gray, contours,
RETR_EXTERNAL,
CHAIN_APPROX_SIMPLE);
for( size_t i = 0; i< contours.size(); i++ )
{
Rect rect = boundingRect(contours[i]);
Mat mask = gray(rect);
Mat srcROI = src(rect);
srcROI.setTo(Scalar(0,0,255),mask);
imshow("srcROI",srcROI);
waitKey();
}
imshow( "result", src );
waitKey(0);
return(0);
}
EDIT: according the change on the question i suggest the test code below
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main( int, char** argv )
{
Mat src = imread("lena.jpg");
vector<Point> points;
points.push_back( Point(200,200));
points.push_back( Point(370,370));
points.push_back( Point(220,410));
Mat mask = Mat::zeros( src.size(), CV_8UC1 );
fillConvexPoly( mask, points, Scalar( 255 ));
Rect rect = boundingRect( points );
Mat roi = src( rect ).clone();
mask = mask( rect ).clone();
rect.x = rect.x - 180;
rect.y = rect.y - 180;
Mat srcROI = src( rect );
roi.copyTo( srcROI, mask );
imshow( "result", src );
waitKey(0);
return(0);
}
As you told that you know co-ordinates of the triangle, using below code you can find triangle.
Mat image = imread("imagePath");
bitwise_not(image, image);
Mat grayImage;
cv::cvtColor(image, grayImage, CV_RGB2GRAY);
cv::vector<cv::vector<cv::Point> > contours;
cv::vector<cv::Vec4i> hierarchy;
cv::findContours(grayImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
Mat contourMat(grayImage.size(), grayImage.type(), Scalar(255));
for(int i = 0; i < contours.size(); i++)
{
if(contours[i].data()->x == 314 && contours[i].data()->y == 37)
drawContours(contourMat, contours, i, Scalar(0), CV_FILLED, 8, hierarchy);
}
imshow("WindowName", contourMat);
Hope this will help.

denoising an image of type CV_16S

I have an array of Mat which contain a lot of noise
I just want to remove the noise in the image but keep the bright object in the image. The image is of type CV_16S and thus is on the scale (-32677, 32676). I tried to do fastNLdenoise but apparently it only works for CV_8UC3 and if I try to convert these images to CV_8UC3, I get a pure white image.
for(long int FrameNumber = startFrame; FrameNumber < endFrame; FrameNumber++){
fp.seekg( BytesPerFrame*(FrameNumber), std::ios::beg);
char buffer[BytesPerImage];
fp.read(buffer, BytesPerImage);
short image[512*512];
short min = 20000, max=1000;
for ( int i = 0; i < BytesPerImage; i=i+2 )
{
int a;
a = floor(i/2)+1;
// take first character
image[a] = (static_cast<unsigned int>(static_cast<unsigned char>(buffer[i+1]))*256+static_cast<unsigned int>(static_cast<unsigned char>(buffer[i])));
if(image[a] < min){
min = image[a];
}
if(image[a] > max){
max = image[a];
}
}
// Processing the image
Mat img(512, 512, CV_16S , image);
img -= (min);
img *= (32676/max); // (330000/2500);
img *= ((max/min)/2) + 2; // 16;
imgArr[FrameNumber-startFrame] = img.clone();
}
Mat mean = ((imgArr[0].clone())/numFrames);
namedWindow( "Mean", WINDOW_AUTOSIZE );// Create a window for display.
for(int i = 1; i<numFrames; i++){
mean += (imgArr[i]/numFrames);
waitKey(50);
}
imshow("Mean", mean);
for(int i = 0; i<numFrames; i++){
Mat temp = imgArr[i].clone();
subtract(imgArr[i].clone(), mean, temp);
GaussianBlur(temp, temp, Size(3,3), 1.5);
imgArr[i] = temp.clone();
}
A sample image produced is shown below:
http://s11.postimg.org/nnhxr7j1f/Screen_Shot_2015_05_27_at_2_51_27_AM.png
Here is my results using simple smoothing using Bilateral Filter. Hope this helps!
Mat mSource_Bgr,mSource_Gray,mBillateral,mBillateral_Gray;
mSource_Bgr= imread(FileName_S.c_str(),1);
bilateralFilter(mSource_Bgr,mBillateral,25,36,100);
imshow("Billateral Smoothing",mBillateral);
Mat mCannyEdge,mThres;
cvtColor(mBillateral,mBillateral_Gray,COLOR_BGR2GRAY);
double CannyAccThresh = threshold(mBillateral_Gray,mThres,0,255,CV_THRESH_BINARY|CV_THRESH_OTSU);
double CannyThresh = 0.1 * CannyAccThresh;
Canny(mBillateral_Gray,mCannyEdge,CannyThresh,CannyAccThresh);
Mat kernal_E,kernal_D;
int erosion_size=1,dilation_size=1;
kernal_E= getStructuringElement( MORPH_RECT,Size( 2*erosion_size + 1, 2*erosion_size+1 ),
Point( erosion_size, erosion_size ) );
kernal_D= getStructuringElement( MORPH_RECT,Size( 2*dilation_size + 1, 2*dilation_size+1 ),
Point( dilation_size, dilation_size ) );
dilate(mCannyEdge,mCannyEdge,kernal_D);
erode(mCannyEdge,mCannyEdge,kernal_E);
imshow("Canny Edge",mCannyEdge);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Find contours
findContours( mCannyEdge.clone(), contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
for (int i = 0; i < contours.size(); i++)
{
drawContours(mSource_Bgr,contours,i,Scalar(0,255,0),2);
}
imshow("Result",mSource_Bgr);