1 | initial version |
Hello Santhosh! Here is a Sample Implementation to find the Edge points of a Contour! Hope this helps!
#include <opencv2\opencv.hpp>
#include "opencv2\opencv_modules.hpp"
using namespace cv;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Mat mSrc= imread("D:\\Conti\\Image Samples\\forum\\Test.png",0);
if(mSrc.empty())
{
cout<< "Invalid Input Image!";
return 0;
}
Mat mSrc_Binary,mSrc_Contours,mEndPoints,mResult;
//Creating a Binary Image
threshold(mSrc,mSrc_Binary,1,255,THRESH_BINARY);
//Make sure it is one Pixel width .i.e to replicate a contour Points
thinning(mSrc_Binary,mSrc_Contours);
Mat_<int> Kernal(3,3);
Kernal << 1, 1, 1,
1,10, 1,
1, 1, 1;
//Multiply the Binary Image with the above Kernal
//Credits & Original Author:
https://stackoverflow.com/questions/26537313/how-can-i-find-endpoints-of-binary-skeleton-image-in-opencv
/*
0 0 1 0 * Kernal 1, 1, 1 => 1 3 12 2
0 1 0 0 1,10, 1 1 11 2 1
0 0 0 0 1, 1, 1 1 1 1 0
*/
filter2D(mSrc_Contours,mEndPoints,CV_8UC1,Kernal);
//We are interested in the pixels whicn are equal to 11
inRange(mEndPoints,11,11,mEndPoints);
//Just adding some Visualization!!
cvtColor(mSrc_Binary,mResult,COLOR_GRAY2BGR);
dilate(mEndPoints, mEndPoints, Mat(), Point(-1, -1), 2, 1, 1);//Make it Visible
mResult.setTo(Scalar(0,0,255),mEndPoints);
imshow("mResult",mResult);
waitKey();
return 0;
}
//Adding this code just for the sake of completion
/**
* Perform one thinning iteration.
* Normally you wouldn't call this function directly from your code.
*
* Parameters:
* im Binary image with range = [0,1]
* iter 0=even, 1=odd
*/
void thinningIteration(cv::Mat& img, int iter)
{
CV_Assert(img.channels() == 1);
CV_Assert(img.depth() != sizeof(uchar));
CV_Assert(img.rows > 3 && img.cols > 3);
cv::Mat marker = cv::Mat::zeros(img.size(), CV_8UC1);
int nRows = img.rows;
int nCols = img.cols;
if (img.isContinuous()) {
nCols *= nRows;
nRows = 1;
}
int x, y;
uchar *pAbove;
uchar *pCurr;
uchar *pBelow;
uchar *nw, *no, *ne; // north (pAbove)
uchar *we, *me, *ea;
uchar *sw, *so, *se; // south (pBelow)
uchar *pDst;
// initialize row pointers
pAbove = NULL;
pCurr = img.ptr<uchar>(0);
pBelow = img.ptr<uchar>(1);
for (y = 1; y < img.rows-1; ++y) {
// shift the rows up by one
pAbove = pCurr;
pCurr = pBelow;
pBelow = img.ptr<uchar>(y+1);
pDst = marker.ptr<uchar>(y);
// initialize col pointers
no = &(pAbove[0]);
ne = &(pAbove[1]);
me = &(pCurr[0]);
ea = &(pCurr[1]);
so = &(pBelow[0]);
se = &(pBelow[1]);
for (x = 1; x < img.cols-1; ++x) {
// shift col pointers left by one (scan left to right)
nw = no;
no = ne;
ne = &(pAbove[x+1]);
we = me;
me = ea;
ea = &(pCurr[x+1]);
sw = so;
so = se;
se = &(pBelow[x+1]);
int A = (*no == 0 && *ne == 1) + (*ne == 0 && *ea == 1) +
(*ea == 0 && *se == 1) + (*se == 0 && *so == 1) +
(*so == 0 && *sw == 1) + (*sw == 0 && *we == 1) +
(*we == 0 && *nw == 1) + (*nw == 0 && *no == 1);
int B = *no + *ne + *ea + *se + *so + *sw + *we + *nw;
int m1 = iter == 0 ? (*no * *ea * *so) : (*no * *ea * *we);
int m2 = iter == 0 ? (*ea * *so * *we) : (*no * *so * *we);
if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0)
pDst[x] = 1;
}
}
img &= ~marker;
}
/**
* Function for thinning the given binary image
*
* Parameters:
* src The source image, binary with range = [0,255]
* dst The destination image
*/
void thinning(const cv::Mat& src, cv::Mat& dst)
{
dst = src.clone();
dst /= 255; // convert to binary image
cv::Mat prev = cv::Mat::zeros(dst.size(), CV_8UC1);
cv::Mat diff;
do {
thinningIteration(dst, 0);
thinningIteration(dst, 1);
cv::absdiff(dst, prev, diff);
dst.copyTo(prev);
}
while (cv::countNonZero(diff) > 0);
//dst *= 255; //We don't need Visualization! Sorry :)!!
}
2 | No.2 Revision |
Hello Santhosh! Here is a Sample Implementation to find the Edge points of a Contour! Hope this helps!
#include <opencv2\opencv.hpp>
#include "opencv2\opencv_modules.hpp"
using namespace cv;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Mat mSrc= imread("D:\\Conti\\Image Samples\\forum\\Test.png",0);
if(mSrc.empty())
{
cout<< "Invalid Input Image!";
return 0;
}
Mat mSrc_Binary,mSrc_Contours,mEndPoints,mResult;
//Creating a Binary Image
threshold(mSrc,mSrc_Binary,1,255,THRESH_BINARY);
//Make sure it is one Pixel width .i.e to replicate a contour Points
thinning(mSrc_Binary,mSrc_Contours);
Mat_<int> Kernal(3,3);
Kernal << 1, 1, 1,
1,10, 1,
1, 1, 1;
//Multiply the Binary Image with the above Kernal
//Credits & Original Author:
https://stackoverflow.com/questions/26537313/how-can-i-find-endpoints-of-binary-skeleton-image-in-opencv
/*
0 0 1 0 * Kernal 1, 1, 1 => 1 3 12 2
0 1 0 0 1,10, 1 1 11 2 1
0 0 0 0 1, 1, 1 1 1 1 0
*/
filter2D(mSrc_Contours,mEndPoints,CV_8UC1,Kernal);
//We are interested in the pixels whicn are equal to 11
inRange(mEndPoints,11,11,mEndPoints);
//Just adding some Visualization!!
cvtColor(mSrc_Binary,mResult,COLOR_GRAY2BGR);
dilate(mEndPoints, mEndPoints, Mat(), Point(-1, -1), 2, 1, 1);//Make it Visible
mResult.setTo(Scalar(0,0,255),mEndPoints);
imshow("mResult",mResult);
waitKey();
return 0;
}
//Adding this code just for the sake of completion
/**
* Perform one thinning iteration.
* Normally you wouldn't call this function directly from your code.
*
* Parameters:
* im Binary image with range = [0,1]
* iter 0=even, 1=odd
*/
void thinningIteration(cv::Mat& img, int iter)
{
CV_Assert(img.channels() == 1);
CV_Assert(img.depth() != sizeof(uchar));
CV_Assert(img.rows > 3 && img.cols > 3);
cv::Mat marker = cv::Mat::zeros(img.size(), CV_8UC1);
int nRows = img.rows;
int nCols = img.cols;
if (img.isContinuous()) {
nCols *= nRows;
nRows = 1;
}
int x, y;
uchar *pAbove;
uchar *pCurr;
uchar *pBelow;
uchar *nw, *no, *ne; // north (pAbove)
uchar *we, *me, *ea;
uchar *sw, *so, *se; // south (pBelow)
uchar *pDst;
// initialize row pointers
pAbove = NULL;
pCurr = img.ptr<uchar>(0);
pBelow = img.ptr<uchar>(1);
for (y = 1; y < img.rows-1; ++y) {
// shift the rows up by one
pAbove = pCurr;
pCurr = pBelow;
pBelow = img.ptr<uchar>(y+1);
pDst = marker.ptr<uchar>(y);
// initialize col pointers
no = &(pAbove[0]);
ne = &(pAbove[1]);
me = &(pCurr[0]);
ea = &(pCurr[1]);
so = &(pBelow[0]);
se = &(pBelow[1]);
for (x = 1; x < img.cols-1; ++x) {
// shift col pointers left by one (scan left to right)
nw = no;
no = ne;
ne = &(pAbove[x+1]);
we = me;
me = ea;
ea = &(pCurr[x+1]);
sw = so;
so = se;
se = &(pBelow[x+1]);
int A = (*no == 0 && *ne == 1) + (*ne == 0 && *ea == 1) +
(*ea == 0 && *se == 1) + (*se == 0 && *so == 1) +
(*so == 0 && *sw == 1) + (*sw == 0 && *we == 1) +
(*we == 0 && *nw == 1) + (*nw == 0 && *no == 1);
int B = *no + *ne + *ea + *se + *so + *sw + *we + *nw;
int m1 = iter == 0 ? (*no * *ea * *so) : (*no * *ea * *we);
int m2 = iter == 0 ? (*ea * *so * *we) : (*no * *so * *we);
if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0)
pDst[x] = 1;
}
}
img &= ~marker;
}
/**
* Function for thinning the given binary image
*
* Parameters:
* src The source image, binary with range = [0,255]
* dst The destination image
*/
void thinning(const cv::Mat& src, cv::Mat& dst)
{
dst = src.clone();
dst /= 255; // convert to binary image
cv::Mat prev = cv::Mat::zeros(dst.size(), CV_8UC1);
cv::Mat diff;
do {
thinningIteration(dst, 0);
thinningIteration(dst, 1);
cv::absdiff(dst, prev, diff);
dst.copyTo(prev);
}
while (cv::countNonZero(diff) > 0);
//dst *= 255; //We don't need Visualization! Sorry :)!!
}
3 | No.3 Revision |
Hello Santhosh! Here is a Sample Implementation to find the Edge points of a Contour! Hope this helps!
#include <opencv2\opencv.hpp>
#include "opencv2\opencv_modules.hpp"
using namespace cv;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Mat mSrc= imread("D:\\Conti\\Image Samples\\forum\\Test.png",0);
if(mSrc.empty())
{
cout<< "Invalid Input Image!";
return 0;
}
Mat mSrc_Binary,mSrc_Contours,mEndPoints,mResult;
//Creating a Binary Image
threshold(mSrc,mSrc_Binary,1,255,THRESH_BINARY);
//Make sure it is one Pixel width .i.e to replicate a contour Points
thinning(mSrc_Binary,mSrc_Contours);
Mat_<int> Kernal(3,3);
Kernal << 1, 1, 1,
1,10, 1,
1, 1, 1;
//Multiply the Binary Image with the above Kernal
//Credits & Original Author:
https://stackoverflow.com/questions/26537313/how-can-i-find-endpoints-of-binary-skeleton-image-in-opencv
/*
0 0 1 0 * Kernal 1, 1, 1 => 1 3 12 2
0 1 0 0 1,10, 1 1 11 2 1
0 0 0 0 1, 1, 1 1 1 1 0
*/
filter2D(mSrc_Contours,mEndPoints,CV_8UC1,Kernal);
//We are interested in the pixels whicn are equal to 11
inRange(mEndPoints,11,11,mEndPoints);
//Just adding some Visualization!!
cvtColor(mSrc_Binary,mResult,COLOR_GRAY2BGR);
dilate(mEndPoints, mEndPoints, Mat(), Point(-1, -1), 2, 1, 1);//Make it Visible
mResult.setTo(Scalar(0,0,255),mEndPoints);
imshow("mResult",mResult);
waitKey();
return 0;
}