1 | initial version |
i have an answer posted before : dilating image before finding contours.
i tried another two ways :
drawing contours thicker and finding contours again.( works slower )
a trial implementation to relocate contour points ( it works faster but it still need to be improved )
the code and results are as follows ( i hope this information will be helpful )
input image:
#include <opencv2/opencv.hpp>
#include <ctime>
using namespace cv;
using namespace std;
vector<vector<Point> > getExpandedContours(Mat binary_img, int pixels, int method)
{
if (method == 0)
{
dilate(binary_img, binary_img, Mat(), Point(-1, -1), pixels);
}
vector<vector<Point> > contours;
findContours(binary_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
if (method == 1)
{
for (int i = 0; i < contours.size(); i++)
{
drawContours(binary_img, contours, i, Scalar(255), pixels * 2);
}
findContours(binary_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
}
if (method == 2)
{
int erosion_value = pixels;
int free_man_cc = -1;
vector<Point> contour;
for (int j = 0; j < contours.size(); j++)
{
contour = contours[j];
int xdiff = 0;
int ydiff = 0;
for (int i = 0; i < contour.size() - 1; i++)
{
Point pt;
if ((contour[i].y > contour[i + 1].y) & (contour[i].x == contour[i + 1].x))
{
free_man_cc = 0;
xdiff = -1 * erosion_value;
ydiff = -1 * erosion_value;
}
if ((contour[i].y > contour[i + 1].y) & (contour[i].x < contour[i + 1].x))
{
free_man_cc = 1;
xdiff = -1 * erosion_value;
ydiff = -1 * erosion_value;
}
if ((contour[i].y == contour[i + 1].y) & (contour[i].x < contour[i + 1].x))
{
free_man_cc = 2;
xdiff = erosion_value;
ydiff = -1 * erosion_value;
}
if ((contour[i].y < contour[i + 1].y) & (contour[i].x < contour[i + 1].x))
{
free_man_cc = 3;
xdiff = erosion_value;
ydiff = -1 * erosion_value;
}
if ((contour[i].y < contour[i + 1].y) & (contour[i].x == contour[i + 1].x))
{
free_man_cc = 4;
xdiff = erosion_value;
ydiff = erosion_value;
}
if ((contour[i].y < contour[i + 1].y) & (contour[i].x > contour[i + 1].x))
{
free_man_cc = 5;
xdiff = erosion_value;
ydiff = erosion_value;
}
if ((contour[i].y == contour[i + 1].y) & (contour[i].x > contour[i + 1].x))
{
free_man_cc = 6;
xdiff = -1 * erosion_value;
ydiff = erosion_value;
}
if ((contour[i].y > contour[i + 1].y) & (contour[i].x > contour[i + 1].x))
{
free_man_cc = 7;
xdiff = -1 * erosion_value;
ydiff = erosion_value;
}
contours[j][i].x = contour[i].x - xdiff;
contours[j][i].y = contour[i].y - ydiff;
}
}
}
return contours;
}
int main(int argc, const char * argv[])
{
Mat img = imread("d:/test.png");
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
gray = gray <127;
std::time_t timeBegin = std::time(0);
double elapsed = 0;
int test_loop = 5000;
int pixel_expansion = 10;
vector<vector<Point> > contours;
for (int i = 0; i < test_loop; i++)
{
double t0 = (double)getTickCount();
contours = getExpandedContours(gray.clone(), pixel_expansion, 0);
elapsed += ((double)getTickCount() - t0) / getTickFrequency();
}
cout << elapsed / test_loop << " seconds (dilating image before finding ) ";
std::time_t timeNow = std::time(0) - timeBegin;
cout << timeNow << endl;
for (int i = 0; i < contours.size(); i++)
{
drawContours(img, contours, i, Scalar(0, 255, 0), 2);
}
imshow("result-0", img);
timeBegin = std::time(0);
elapsed = 0;
for (int i = 0; i < test_loop; i++)
{
double t0 = (double)getTickCount();
contours = getExpandedContours(gray.clone(), pixel_expansion, 1);
elapsed += ((double)getTickCount() - t0) / getTickFrequency();
}
cout << elapsed / test_loop << " seconds (drawing contours thicker and finding contours again) ";
timeNow = std::time(0) - timeBegin;
cout << timeNow << endl;
for (int i = 0; i < contours.size(); i++)
{
drawContours(img, contours, i, Scalar(0, 0, 255), 2);
}
imshow("result-1", img);
timeBegin = std::time(0);
elapsed = 0;
for (int i = 0; i < test_loop; i++)
{
double t0 = (double)getTickCount();
contours = getExpandedContours(gray.clone(), pixel_expansion, 2);
elapsed += ((double)getTickCount() - t0) / getTickFrequency();
}
cout << elapsed / test_loop << " seconds (new trial method) ";
timeNow = std::time(0) - timeBegin;
cout << timeNow << endl;
for (int i = 0; i < contours.size(); i++)
{
drawContours(img, contours, i, Scalar(255, 0, 0), 2);
}
imshow("result-2", img);
waitKey();
return 0;
}
2 | No.2 Revision |
i have an answer posted before : dilating image before finding contours.
We can do eroding image before finding contours to get opposite effect.
additionally i tried another two ways :
drawing contours thicker and finding contours again.( works slower )
a trial implementation to relocate contour points ( it works faster but it still need to be improved )
the code and results are as follows ( i hope this information will be helpful )
Performans comparison
***************************
0.00119661 seconds (dilating image before finding contours ) 0
0.0071249 seconds (drawing contours thicker and finding contours again) 4
0.000708922 seconds (new trial method) 0
0.00113688 seconds (eroding image before finding contours ) 1
0.0046207 seconds (drawing contours thicker with Scalar(0) and finding contours again) 2
input image:
Output images:
#include <opencv2/opencv.hpp>
#include <ctime>
using namespace cv;
using namespace std;
vector<vector<Point> > getExpandedContours(Mat binary_img, int pixels, int method)
{
if (method == 0)
{
dilate(binary_img, binary_img, Mat(), Point(-1, -1), pixels);
}
vector<vector<Point> > contours;
findContours(binary_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
if (method == 1)
{
for (int i = 0; i < contours.size(); i++)
{
drawContours(binary_img, contours, i, Scalar(255), pixels * 2);
}
findContours(binary_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
}
if (method == 2)
{
int erosion_value = pixels;
int free_man_cc = -1;
vector<Point> contour;
for (int j = 0; j < contours.size(); j++)
{
contour = contours[j];
int xdiff = 0;
int ydiff = 0;
for (int i = 0; i < contour.size() - 1; i++)
{
Point pt;
if ((contour[i].y > contour[i + 1].y) & (contour[i].x == contour[i + 1].x))
{
free_man_cc = 0;
xdiff = -1 * erosion_value;
ydiff = -1 * erosion_value;
}
if ((contour[i].y > contour[i + 1].y) & (contour[i].x < contour[i + 1].x))
{
free_man_cc = 1;
xdiff = -1 * erosion_value;
ydiff = -1 * erosion_value;
}
if ((contour[i].y == contour[i + 1].y) & (contour[i].x < contour[i + 1].x))
{
free_man_cc = 2;
xdiff = erosion_value;
ydiff = -1 * erosion_value;
}
if ((contour[i].y < contour[i + 1].y) & (contour[i].x < contour[i + 1].x))
{
free_man_cc = 3;
xdiff = erosion_value;
ydiff = -1 * erosion_value;
}
if ((contour[i].y < contour[i + 1].y) & (contour[i].x == contour[i + 1].x))
{
free_man_cc = 4;
xdiff = erosion_value;
ydiff = erosion_value;
}
if ((contour[i].y < contour[i + 1].y) & (contour[i].x > contour[i + 1].x))
{
free_man_cc = 5;
xdiff = erosion_value;
ydiff = erosion_value;
}
if ((contour[i].y == contour[i + 1].y) & (contour[i].x > contour[i + 1].x))
{
free_man_cc = 6;
xdiff = -1 * erosion_value;
ydiff = erosion_value;
}
if ((contour[i].y > contour[i + 1].y) & (contour[i].x > contour[i + 1].x))
{
free_man_cc = 7;
xdiff = -1 * erosion_value;
ydiff = erosion_value;
}
contours[j][i].x = contour[i].x - xdiff;
contours[j][i].y = contour[i].y - ydiff;
}
}
}
return contours;
}
vector<vector<Point> > getShrinkedContours(Mat binary_img, int pixels, int method)
{
if (method == 0)
{
erode(binary_img, binary_img, Mat(), Point(-1, -1), pixels);
}
vector<vector<Point> > contours;
findContours(binary_img.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
if (method == 1)
{
for (int i = 0; i < contours.size(); i++)
{
drawContours(binary_img, contours, i, Scalar(0), pixels * 2);
}
findContours(binary_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
}
return contours;
}
int main(int argc, const char * argv[])
{
Mat img = imread("d:/test.png");
Mat img0 = img.clone();
Mat img1 = img.clone();
Mat img2 = img.clone();
Mat img3 = img.clone();
Mat img4 = img.clone();
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
gray = gray <127;
std::time_t timeBegin = std::time(0);
double elapsed = 0;
int test_loop = 5000;
500;
int pixel_expansion = 10;
vector<vector<Point> > contours;
for (int i = 0; i < test_loop; i++)
{
double t0 = (double)getTickCount();
contours = getExpandedContours(gray.clone(), pixel_expansion, 0);
elapsed += ((double)getTickCount() - t0) / getTickFrequency();
}
cout << elapsed / test_loop << " seconds (dilating image before finding contours ) ";
std::time_t timeNow = std::time(0) - timeBegin;
cout << timeNow << endl;
for (int i = 0; i < contours.size(); i++)
{
drawContours(img, drawContours(img0, contours, i, Scalar(0, 255, 0), 2);
}
imshow("result-0", img);
img0);
timeBegin = std::time(0);
elapsed = 0;
for (int i = 0; i < test_loop; i++)
{
double t0 = (double)getTickCount();
contours = getExpandedContours(gray.clone(), pixel_expansion, 1);
elapsed += ((double)getTickCount() - t0) / getTickFrequency();
}
cout << elapsed / test_loop << " seconds (drawing contours thicker with Scalar(255) and finding contours again) ";
timeNow = std::time(0) - timeBegin;
cout << timeNow << endl;
for (int i = 0; i < contours.size(); i++)
{
drawContours(img, drawContours(img1, contours, i, Scalar(0, 0, 255), 2);
}
imshow("result-1", img);
img1);
timeBegin = std::time(0);
elapsed = 0;
for (int i = 0; i < test_loop; i++)
{
double t0 = (double)getTickCount();
contours = getExpandedContours(gray.clone(), pixel_expansion, 2);
elapsed += ((double)getTickCount() - t0) / getTickFrequency();
}
cout << elapsed / test_loop << " seconds (new trial method) ";
timeNow = std::time(0) - timeBegin;
cout << timeNow << endl;
for (int i = 0; i < contours.size(); i++)
{
drawContours(img, drawContours(img2, contours, i, Scalar(255, 0, 0), 2);
}
imshow("result-2", img);
img2);
timeBegin = std::time(0);
elapsed = 0;
for (int i = 0; i < test_loop; i++)
{
double t0 = (double)getTickCount();
contours = getShrinkedContours(gray.clone(), pixel_expansion/2, 0);
elapsed += ((double)getTickCount() - t0) / getTickFrequency();
}
cout << elapsed / test_loop << " seconds (eroding image before finding contours ) ";
timeNow = std::time(0) - timeBegin;
cout << timeNow << endl;
for (int i = 0; i < contours.size(); i++)
{
drawContours(img3, contours, i, Scalar(0, 255, 0), 2);
}
imshow("result-3", img3);
timeBegin = std::time(0);
elapsed = 0;
for (int i = 0; i < test_loop; i++)
{
double t0 = (double)getTickCount();
contours = getShrinkedContours(gray.clone(), pixel_expansion /2, 1);
elapsed += ((double)getTickCount() - t0) / getTickFrequency();
}
cout << elapsed / test_loop << " seconds (drawing contours thicker with Scalar(0) and finding contours again) ";
timeNow = std::time(0) - timeBegin;
cout << timeNow << endl;
for (int i = 0; i < contours.size(); i++)
{
drawContours(img4, contours, i, Scalar(0, 0, 255), 2);
}
imshow("result-4", img4);
waitKey();
return 0;
}