1 | initial version |
Here is a Sample implementation of Contour based and Image based edge-smoothing algorithms! Hope this helps!
#include <iostream>
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
bool SmoothEdgeSingleChannel( Mat mInput,Mat &mOutput, double amount, double radius, uchar Threshold) ;
bool SmoothEdge( Mat mInput_Bgr,Mat &mOutput_Bgr, double amount, double radius, uchar Threshold)
{
if(mInput_Bgr.empty())
{
return 0;
}
if(radius<1)
radius=1;
Mat mInput,mOutput;
Mat mChannel[3];
split(mInput_Bgr,mChannel);
for (int i = 0; i < 3; i++)
{
mInput= mChannel[i];
SmoothEdgeSingleChannel(mInput,mOutput,amount, radius,Threshold);
mOutput.copyTo(mChannel[i]);
}
merge(mChannel,3,mOutput_Bgr);
return true;
}
bool SmoothEdgeSingleChannel( Mat mInput,Mat &mOutput, double amount, double radius, uchar Threshold)
{
if(mInput.empty())
{
return 0;
}
if(radius<1)
radius=1;
Mat mGSmooth,mDiff,mAbsDiff;
mOutput = Mat(mInput.size(),mInput.type());
GaussianBlur(mInput,mGSmooth,Size(0,0),radius);
//imshow("mGSmooth",mGSmooth);
subtract(mGSmooth,mInput,mDiff);
//imshow("mDiff",mDiff);
mDiff*=amount;
threshold(abs(2* mDiff),mAbsDiff,Threshold,255,THRESH_BINARY_INV);
mDiff.setTo(Scalar(0),mAbsDiff);
//imshow("mDiff Multiplied",mDiff);
add(mInput,mDiff,mOutput);
return true;
}
//Credits: http://stackoverflow.com/questions/34527349/non-connecting-morphological-filter/34535023#34535023
bool SmoothContours(vector<vector<Point>> contours_Src,vector<vector<Point>> &contours_Smooth,int Radius,double Sigma )
{
if(contours_Src.size()==0)
return false;
int FilterSize = 2 * Radius + 1;
for (int id = 0; id < contours_Src.size(); id++)
{
size_t len = contours_Src[id].size() + 2 * Radius;
size_t idx = (contours_Src[id].size() - Radius);
vector<float> x, y;
vector<float> xFilt, yFilt;
vector<Point> contours_Smooth_Curr;
for (size_t i = 0; i < len; i++)
{
x.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].x);
y.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].y);
}
GaussianBlur(x, xFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
GaussianBlur(y, yFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
for (size_t i = Radius; i < contours_Src[id].size() + Radius; i++)
{
contours_Smooth_Curr.push_back(Point(xFilt[i], yFilt[i]));
}
contours_Smooth.push_back(contours_Smooth_Curr);
}
return true;
}
int main(int argc, char* argv[])
{
string FileName_S="D:\\Image samples\\Input.png";
Mat mSource,mThres,mResult,mSmoothEdge;
mSource= imread(FileName_S,0);
RNG rng(12345);
if(mSource.empty())
{
cout<<"[Error] Invalid Input Image!";
return 0;
}
mSmoothEdge= mSource.clone();
mSmoothEdge.setTo(0);
threshold(mSource,mThres,125,255,THRESH_BINARY_INV);
imshow("Source mThres",mThres);
cvtColor(mSource,mResult,COLOR_GRAY2BGR);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
vector<vector<Point>> contours_Smoothed;
int Radius=1;
double Sigma=2.0;
findContours( mThres.clone(), contours, hierarchy, RETR_TREE, CV_CHAIN_APPROX_SIMPLE );
//Smoothing Contour Points using Gaussian Smooth!
SmoothContours(contours,contours_Smoothed,Radius,Sigma);
for( size_t i = 0; i< contours.size(); i++ )
{
/*Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( mResult, contours, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );*/
if(hierarchy[i][2]<0)//These are inner most child contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(0), -1, 8, vector<Vec4i>(), 0, Point() );
}
if(hierarchy[i][3]<0)//These are outer most parent contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(255), -1, 8, vector<Vec4i>(), 0, Point() );
}
}
//imshow("Source Image",mResult);
imshow("1) Smooth Edge Points",mSmoothEdge);
//Smoothing Edge using Modified Unsharp Masking
mSmoothEdge.setTo(0);
SmoothEdgeSingleChannel(mThres,mSmoothEdge,2.5,1.0,254);
imshow("2) Smooth Edges",mSmoothEdge);
waitKey();
}
2 | No.2 Revision |
Here is a Sample implementation of Contour based and Image based edge-smoothing algorithms! Hope this helps!
#include <iostream>
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
string FileName_S="D:\\Image samples\\Input.png";
Mat mSource,mThres,mResult,mSmoothEdge;
mSource= imread(FileName_S,0);
RNG rng(12345);
if(mSource.empty())
{
cout<<"[Error] Invalid Input Image!";
return 0;
}
mSmoothEdge= mSource.clone();
mSmoothEdge.setTo(0);
threshold(mSource,mThres,125,255,THRESH_BINARY_INV);
imshow("Source mThres",mThres);
cvtColor(mSource,mResult,COLOR_GRAY2BGR);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
vector<vector<Point>> contours_Smoothed;
int Radius=1;
double Sigma=2.0;
findContours( mThres.clone(), contours, hierarchy, RETR_TREE, CV_CHAIN_APPROX_SIMPLE );
//Smoothing Contour Points using Gaussian Smooth!
SmoothContours(contours,contours_Smoothed,Radius,Sigma);
for( size_t i = 0; i< contours.size(); i++ )
{
/*Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( mResult, contours, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );*/
if(hierarchy[i][2]<0)//These are inner most child contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(0), -1, 8, vector<Vec4i>(), 0, Point() );
}
if(hierarchy[i][3]<0)//These are outer most parent contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(255), -1, 8, vector<Vec4i>(), 0, Point() );
}
}
//imshow("Source Image",mResult);
imshow("1) Smooth Edge Points",mSmoothEdge);
//Smoothing Edge using Modified Unsharp Masking
mSmoothEdge.setTo(0);
SmoothEdgeSingleChannel(mThres,mSmoothEdge,2.5,1.0,254);
imshow("2) Smooth Edges",mSmoothEdge);
waitKey();
}
bool SmoothEdgeSingleChannel( Mat mInput,Mat &mOutput, double amount, double radius, uchar Threshold) ;
bool SmoothEdge( Mat mInput_Bgr,Mat &mOutput_Bgr, double amount, double radius, uchar Threshold)
{
if(mInput_Bgr.empty())
{
return 0;
}
if(radius<1)
radius=1;
Mat mInput,mOutput;
Mat mChannel[3];
split(mInput_Bgr,mChannel);
for (int i = 0; i < 3; i++)
{
mInput= mChannel[i];
SmoothEdgeSingleChannel(mInput,mOutput,amount, radius,Threshold);
mOutput.copyTo(mChannel[i]);
}
merge(mChannel,3,mOutput_Bgr);
return true;
}
bool SmoothEdgeSingleChannel( Mat mInput,Mat &mOutput, double amount, double radius, uchar Threshold)
{
if(mInput.empty())
{
return 0;
}
if(radius<1)
radius=1;
Mat mGSmooth,mDiff,mAbsDiff;
mOutput = Mat(mInput.size(),mInput.type());
GaussianBlur(mInput,mGSmooth,Size(0,0),radius);
//imshow("mGSmooth",mGSmooth);
subtract(mGSmooth,mInput,mDiff);
//imshow("mDiff",mDiff);
mDiff*=amount;
threshold(abs(2* mDiff),mAbsDiff,Threshold,255,THRESH_BINARY_INV);
mDiff.setTo(Scalar(0),mAbsDiff);
//imshow("mDiff Multiplied",mDiff);
add(mInput,mDiff,mOutput);
return true;
}
//Credits: http://stackoverflow.com/questions/34527349/non-connecting-morphological-filter/34535023#34535023
bool SmoothContours(vector<vector<Point>> contours_Src,vector<vector<Point>> &contours_Smooth,int Radius,double Sigma )
{
if(contours_Src.size()==0)
return false;
int FilterSize = 2 * Radius + 1;
for (int id = 0; id < contours_Src.size(); id++)
{
size_t len = contours_Src[id].size() + 2 * Radius;
size_t idx = (contours_Src[id].size() - Radius);
vector<float> x, y;
vector<float> xFilt, yFilt;
vector<Point> contours_Smooth_Curr;
for (size_t i = 0; i < len; i++)
{
x.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].x);
y.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].y);
}
GaussianBlur(x, xFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
GaussianBlur(y, yFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
for (size_t i = Radius; i < contours_Src[id].size() + Radius; i++)
{
contours_Smooth_Curr.push_back(Point(xFilt[i], yFilt[i]));
}
contours_Smooth.push_back(contours_Smooth_Curr);
}
return true;
}
int main(int argc, char* argv[])
{
string FileName_S="D:\\Image samples\\Input.png";
Mat mSource,mThres,mResult,mSmoothEdge;
mSource= imread(FileName_S,0);
RNG rng(12345);
if(mSource.empty())
{
cout<<"[Error] Invalid Input Image!";
return 0;
}
mSmoothEdge= mSource.clone();
mSmoothEdge.setTo(0);
threshold(mSource,mThres,125,255,THRESH_BINARY_INV);
imshow("Source mThres",mThres);
cvtColor(mSource,mResult,COLOR_GRAY2BGR);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
vector<vector<Point>> contours_Smoothed;
int Radius=1;
double Sigma=2.0;
findContours( mThres.clone(), contours, hierarchy, RETR_TREE, CV_CHAIN_APPROX_SIMPLE );
//Smoothing Contour Points using Gaussian Smooth!
SmoothContours(contours,contours_Smoothed,Radius,Sigma);
for( size_t i = 0; i< contours.size(); i++ )
{
/*Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( mResult, contours, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );*/
if(hierarchy[i][2]<0)//These are inner most child contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(0), -1, 8, vector<Vec4i>(), 0, Point() );
}
if(hierarchy[i][3]<0)//These are outer most parent contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(255), -1, 8, vector<Vec4i>(), 0, Point() );
}
}
//imshow("Source Image",mResult);
imshow("1) Smooth Edge Points",mSmoothEdge);
//Smoothing Edge using Modified Unsharp Masking
mSmoothEdge.setTo(0);
SmoothEdgeSingleChannel(mThres,mSmoothEdge,2.5,1.0,254);
imshow("2) Smooth Edges",mSmoothEdge);
waitKey();
}
3 | No.3 Revision |
Here is a Sample implementation of Contour based and Image based edge-smoothing algorithms! Hope this helps!
#include <iostream>
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
string FileName_S="D:\\Image samples\\Input.png";
Mat mSource,mThres,mResult,mSmoothEdge;
mSource= imread(FileName_S,0);
RNG rng(12345);
if(mSource.empty())
{
cout<<"[Error] Invalid Input Image!";
return 0;
}
mSmoothEdge= mSource.clone();
mSmoothEdge.setTo(0);
threshold(mSource,mThres,125,255,THRESH_BINARY_INV);
imshow("Source mThres",mThres);
cvtColor(mSource,mResult,COLOR_GRAY2BGR);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
vector<vector<Point>> contours_Smoothed;
int Radius=1;
double Sigma=2.0;
findContours( mThres.clone(), contours, hierarchy, RETR_TREE, CV_CHAIN_APPROX_SIMPLE );
//Smoothing Contour Points using Gaussian Smooth!
SmoothContours(contours,contours_Smoothed,Radius,Sigma);
for( size_t i = 0; i< contours.size(); i++ )
{
/*Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( mResult, contours, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );*/
if(hierarchy[i][2]<0)//These are inner most child contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(0), -1, 8, vector<Vec4i>(), 0, Point() );
}
if(hierarchy[i][3]<0)//These are outer most parent contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(255), -1, 8, vector<Vec4i>(), 0, Point() );
}
}
//imshow("Source Image",mResult);
imshow("1) Smooth Edge Points",mSmoothEdge);
//Smoothing Edge using Modified Unsharp Masking
mSmoothEdge.setTo(0);
SmoothEdgeSingleChannel(mThres,mSmoothEdge,2.5,1.0,254);
imshow("2) Smooth Edges",mSmoothEdge);
waitKey();
}
bool SmoothEdge( Mat mInput_Bgr,Mat &mOutput_Bgr, double amount, double radius, uchar Threshold)
{
if(mInput_Bgr.empty())
{
return 0;
}
if(radius<1)
radius=1;
Mat mInput,mOutput;
Mat mChannel[3];
split(mInput_Bgr,mChannel);
for (int i = 0; i < 3; i++)
{
mInput= mChannel[i];
SmoothEdgeSingleChannel(mInput,mOutput,amount, radius,Threshold);
mOutput.copyTo(mChannel[i]);
}
merge(mChannel,3,mOutput_Bgr);
return true;
}
bool SmoothEdgeSingleChannel( Mat mInput,Mat &mOutput, double amount, double radius, uchar Threshold) ;
bool SmoothEdge( Mat mInput_Bgr,Mat &mOutput_Bgr, double amount, double radius, uchar Threshold)
{
if(mInput_Bgr.empty())
{
return 0;
}
if(radius<1)
radius=1;
Mat mInput,mOutput;
Mat mChannel[3];
split(mInput_Bgr,mChannel);
for (int i = 0; i < 3; i++)
{
mInput= mChannel[i];
SmoothEdgeSingleChannel(mInput,mOutput,amount, radius,Threshold);
mOutput.copyTo(mChannel[i]);
}
merge(mChannel,3,mOutput_Bgr);
return true;
}
bool SmoothEdgeSingleChannel( Mat mInput,Mat &mOutput, double amount, double radius, uchar Threshold)
{
if(mInput.empty())
{
return 0;
}
if(radius<1)
radius=1;
Mat mGSmooth,mDiff,mAbsDiff;
mOutput = Mat(mInput.size(),mInput.type());
GaussianBlur(mInput,mGSmooth,Size(0,0),radius);
//imshow("mGSmooth",mGSmooth);
subtract(mGSmooth,mInput,mDiff);
//imshow("mDiff",mDiff);
mDiff*=amount;
threshold(abs(2* mDiff),mAbsDiff,Threshold,255,THRESH_BINARY_INV);
mDiff.setTo(Scalar(0),mAbsDiff);
//imshow("mDiff Multiplied",mDiff);
add(mInput,mDiff,mOutput);
return true;
}
//Credits: http://stackoverflow.com/questions/34527349/non-connecting-morphological-filter/34535023#34535023
bool SmoothContours(vector<vector<Point>> contours_Src,vector<vector<Point>> &contours_Smooth,int Radius,double Sigma )
{
if(contours_Src.size()==0)
return false;
int FilterSize = 2 * Radius + 1;
for (int id = 0; id < contours_Src.size(); id++)
{
size_t len = contours_Src[id].size() + 2 * Radius;
size_t idx = (contours_Src[id].size() - Radius);
vector<float> x, y;
vector<float> xFilt, yFilt;
vector<Point> contours_Smooth_Curr;
for (size_t i = 0; i < len; i++)
{
x.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].x);
y.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].y);
}
GaussianBlur(x, xFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
GaussianBlur(y, yFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
for (size_t i = Radius; i < contours_Src[id].size() + Radius; i++)
{
contours_Smooth_Curr.push_back(Point(xFilt[i], yFilt[i]));
}
contours_Smooth.push_back(contours_Smooth_Curr);
}
return true;
}
4 | No.4 Revision |
Here is a Sample implementation of Contour based and Image based edge-smoothing algorithms! Hope this helps!
#include <iostream>
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
string FileName_S="D:\\Image samples\\Input.png";
Mat mSource,mThres,mResult,mSmoothEdge;
mSource= imread(FileName_S,0);
RNG rng(12345);
if(mSource.empty())
{
cout<<"[Error] Invalid Input Image!";
return 0;
}
mSmoothEdge= mSource.clone();
mSmoothEdge.setTo(0);
threshold(mSource,mThres,125,255,THRESH_BINARY_INV);
threshold(mSource,mThres,125,255,THRESH_BINARY);
imshow("Source mThres",mThres);
cvtColor(mSource,mResult,COLOR_GRAY2BGR);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
vector<vector<Point>> contours_Smoothed;
int Radius=1;
double Sigma=2.0;
findContours( mThres.clone(), contours, hierarchy, RETR_TREE, CV_CHAIN_APPROX_SIMPLE );
//Smoothing Contour Points using Gaussian Smooth!
SmoothContours(contours,contours_Smoothed,Radius,Sigma);
for( size_t i = 0; i< contours.size(); i++ )
{
/*Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( mResult, contours, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );*/
if(hierarchy[i][2]<0)//These are inner most child contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(0), -1, 8, LINE_AA, vector<Vec4i>(), 0, Point() );
}
if(hierarchy[i][3]<0)//These are outer most parent contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(255), -1, 8, LINE_AA, vector<Vec4i>(), 0, Point() );
}
}
//imshow("Source Image",mResult);
imshow("1) Smooth Edge Points",mSmoothEdge);
//Smoothing Edge using Modified Unsharp Masking
mSmoothEdge.setTo(0);
SmoothEdgeSingleChannel(mThres,mSmoothEdge,2.5,1.0,254);
imshow("2) Smooth Edges",mSmoothEdge);
waitKey();
}
bool SmoothEdge( Mat mInput_Bgr,Mat &mOutput_Bgr, double amount, double radius, uchar Threshold)
{
if(mInput_Bgr.empty())
{
return 0;
}
if(radius<1)
radius=1;
Mat mInput,mOutput;
Mat mChannel[3];
split(mInput_Bgr,mChannel);
for (int i = 0; i < 3; i++)
{
mInput= mChannel[i];
SmoothEdgeSingleChannel(mInput,mOutput,amount, radius,Threshold);
mOutput.copyTo(mChannel[i]);
}
merge(mChannel,3,mOutput_Bgr);
return true;
}
bool SmoothEdgeSingleChannel( Mat mInput,Mat &mOutput, double amount, double radius, uchar Threshold)
{
if(mInput.empty())
{
return 0;
}
if(radius<1)
radius=1;
Mat mGSmooth,mDiff,mAbsDiff;
mOutput = Mat(mInput.size(),mInput.type());
GaussianBlur(mInput,mGSmooth,Size(0,0),radius);
//imshow("mGSmooth",mGSmooth);
subtract(mGSmooth,mInput,mDiff);
//imshow("mDiff",mDiff);
mDiff*=amount;
threshold(abs(2* mDiff),mAbsDiff,Threshold,255,THRESH_BINARY_INV);
mDiff.setTo(Scalar(0),mAbsDiff);
//imshow("mDiff Multiplied",mDiff);
add(mInput,mDiff,mOutput);
return true;
}
//Credits: http://stackoverflow.com/questions/34527349/non-connecting-morphological-filter/34535023#34535023
bool SmoothContours(vector<vector<Point>> contours_Src,vector<vector<Point>> &contours_Smooth,int Radius,double Sigma )
{
if(contours_Src.size()==0)
return false;
int FilterSize = 2 * Radius + 1;
for (int id = 0; id < contours_Src.size(); id++)
{
size_t len = contours_Src[id].size() + 2 * Radius;
size_t idx = (contours_Src[id].size() - Radius);
vector<float> x, y;
vector<float> xFilt, yFilt;
vector<Point> contours_Smooth_Curr;
for (size_t i = 0; i < len; i++)
{
x.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].x);
y.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].y);
}
GaussianBlur(x, xFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
GaussianBlur(y, yFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
for (size_t i = Radius; i < contours_Src[id].size() + Radius; i++)
{
contours_Smooth_Curr.push_back(Point(xFilt[i], yFilt[i]));
}
contours_Smooth.push_back(contours_Smooth_Curr);
}
return true;
}
5 | No.5 Revision |
Here is a Sample implementation of Contour based and Image based edge-smoothing algorithms! Hope this helps!
#include <iostream>
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
string FileName_S="D:\\Image samples\\Input.png";
Mat mSource,mThres,mResult,mSmoothEdge;
mSource= imread(FileName_S,0);
//Source Image
RNG rng(12345);
if(mSource.empty())
{
cout<<"[Error] Invalid Input Image!";
return 0;
}
mSmoothEdge= mSource.clone();
mSmoothEdge.setTo(0);
threshold(mSource,mThres,125,255,THRESH_BINARY);
imshow("Source mThres",mThres);
cvtColor(mSource,mResult,COLOR_GRAY2BGR);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
vector<vector<Point>> contours_Smoothed;
int Radius=1;
double Sigma=2.0;
findContours( mThres.clone(), contours, hierarchy, RETR_TREE, CV_CHAIN_APPROX_SIMPLE );
//Smoothing Contour Points using Gaussian Smooth!
SmoothContours(contours,contours_Smoothed,Radius,Sigma);
for( size_t i = 0; i< contours.size(); i++ )
{
/*Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( mResult, contours, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );*/
if(hierarchy[i][2]<0)//These are inner most child contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(0), -1, LINE_AA, vector<Vec4i>(), 0, Point() );
}
if(hierarchy[i][3]<0)//These are outer most parent contours
{
drawContours( mSmoothEdge, contours_Smoothed, i, Scalar(255), -1, LINE_AA, vector<Vec4i>(), 0, Point() );
}
}
//imshow("Source Image",mResult);
imshow("1) Smooth Edge Points",mSmoothEdge);
//Smoothing Edge using Modified Unsharp Masking
mSmoothEdge.setTo(0);
SmoothEdgeSingleChannel(mThres,mSmoothEdge,2.5,1.0,254);
imshow("2) Smooth Edges",mSmoothEdge);
waitKey();
}
bool SmoothEdge( Mat mInput_Bgr,Mat &mOutput_Bgr, double amount, double radius, uchar Threshold)
{
if(mInput_Bgr.empty())
{
return 0;
}
if(radius<1)
radius=1;
Mat mInput,mOutput;
Mat mChannel[3];
split(mInput_Bgr,mChannel);
for (int i = 0; i < 3; i++)
{
mInput= mChannel[i];
SmoothEdgeSingleChannel(mInput,mOutput,amount, radius,Threshold);
mOutput.copyTo(mChannel[i]);
}
merge(mChannel,3,mOutput_Bgr);
return true;
}
bool SmoothEdgeSingleChannel( Mat mInput,Mat &mOutput, double amount, double radius, uchar Threshold)
{
if(mInput.empty())
{
return 0;
}
if(radius<1)
radius=1;
Mat mGSmooth,mDiff,mAbsDiff;
mOutput = Mat(mInput.size(),mInput.type());
GaussianBlur(mInput,mGSmooth,Size(0,0),radius);
//imshow("mGSmooth",mGSmooth);
subtract(mGSmooth,mInput,mDiff);
//imshow("mDiff",mDiff);
mDiff*=amount;
threshold(abs(2* mDiff),mAbsDiff,Threshold,255,THRESH_BINARY_INV);
mDiff.setTo(Scalar(0),mAbsDiff);
//imshow("mDiff Multiplied",mDiff);
add(mInput,mDiff,mOutput);
return true;
}
//Credits: http://stackoverflow.com/questions/34527349/non-connecting-morphological-filter/34535023#34535023
bool SmoothContours(vector<vector<Point>> contours_Src,vector<vector<Point>> &contours_Smooth,int Radius,double Sigma )
{
if(contours_Src.size()==0)
return false;
int FilterSize = 2 * Radius + 1;
for (int id = 0; id < contours_Src.size(); id++)
{
size_t len = contours_Src[id].size() + 2 * Radius;
size_t idx = (contours_Src[id].size() - Radius);
vector<float> x, y;
vector<float> xFilt, yFilt;
vector<Point> contours_Smooth_Curr;
for (size_t i = 0; i < len; i++)
{
x.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].x);
y.push_back(contours_Src[id][(idx + i) % contours_Src[id].size()].y);
}
GaussianBlur(x, xFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
GaussianBlur(y, yFilt, Size(FilterSize, FilterSize), Sigma, Sigma);
for (size_t i = Radius; i < contours_Src[id].size() + Radius; i++)
{
contours_Smooth_Curr.push_back(Point(xFilt[i], yFilt[i]));
}
contours_Smooth.push_back(contours_Smooth_Curr);
}
return true;
}