High-quality-ellipse-detection icon indicating copy to clipboard operation
High-quality-ellipse-detection copied to clipboard

Wrong output of the ellipse detector in C++

Open IaBogdi opened this issue 4 years ago • 10 comments

Dear developer,

I attempted to change the code so it could run on C++. In file generateEllipseCandidates.cpp I replaced mexFunction by the following one:

void ellipse_detector(Mat& img, int edge_process_select, int specified_polarity, double* candidates_out, Mat& out_mat) {
	uchar * inputimg = img.data;
	int imgy, imgx;
	imgy = img.cols;
	imgx = img.rows;
	double *data = (double*)malloc(imgy*imgx * sizeof(double));
	for (int c = 0; c<imgx; c++)
	{
		for (int r = 0; r<imgy; r++)
		{
			data[c + r*imgx] = inputimg[r + c*imgy];
		}
	}
	int n;
	std::vector<std::vector<int> > groups;
	double * coverages;
	int * reg;
	int reg_x;
	int reg_y;
	double* out = mylsd(&n, data, imgx, imgy, &reg, &reg_x, &reg_y);
	groupLSs(out, n, reg, reg_x, reg_y, &groups);
	free(reg);
	calcuGroupCoverage(out, n, groups, coverages);

	printf("The number of output arc-support line segments: %i\n", n);
	printf("The number of arc-support groups:%i\n", groups.size());
	image_double angles;
	if (edge_process_select == 1)
		calculateGradient2(data, imgx, imgy, &angles); //version2, sobel; version 3 canny
	else
		calculateGradient3(data, imgx, imgy, &angles); //version2, sobel; version 3 canny
	PairGroupList * pairGroupList;
	double distance_tolerance = 2;
	printf("Tolerance: %f \n", distance_tolerance);
	double * candidates;
	int  candidates_num;//��ѡ��Բ����
							//rejectShortLines(out,n,&new_n);
	pairGroupList = getValidInitialEllipseSet(out, n, &groups, coverages, angles, distance_tolerance, specified_polarity);
	if (pairGroupList != NULL)
	{
		printf("The number of initial ellipses %i \n", pairGroupList->length);
		generateEllipseCandidates(pairGroupList, distance_tolerance, candidates, &candidates_num);
		printf("The number of ellipse candidates: %i \n", candidates_num);
		candidates_out = (double*) malloc(sizeof(double) * 5 * candidates_num);
		memcpy(candidates_out, candidates, sizeof(double) * 5 * candidates_num);
		//��ѡԲ���(xi,yi,ai,bi,phi_i)', 5 x candidates_num, ���Ƶ�����candidates_out��
		freePairGroupList(pairGroupList);
	}
	else
	{
		candidates_num = 0;
		printf("The number of initial ellipses %i \n", 0);
		candidates_out = (double*)malloc(5 * sizeof(double));
		candidates_out[0] = candidates_out[1] = candidates_out[2] = candidates_out[3] = candidates_out[4] = 0;
	}
	transpose(img, out_mat);
	for (int i = 0; i<n; i++)//draw lines
	{
		Point2d p1(out[8 * i], out[8 * i + 1]), p2(out[8 * i + 2], out[8 * i + 3]);
		line(out_mat, p1, p2, Scalar(255, 0, 0));
	}
	if (candidates_num > 0)//draw ellipses
	{
		for (int i = 0; i<candidates_num; i++)
			ellipse(out_mat, cv::Point((int)candidates_out[i * 5], (int)candidates_out[i * 5 + 1]), cv::Size(candidates_out[i * 5 + 2], candidates_out[i * 5 + 3]), candidates_out[i * 5 + 4] * 180 / M_PI, 0, 360, (Scalar(255, 0, 0)), 1);
	}
	free(data);
	free(coverages);
	free(out);
	free_image_double(angles);

}

and main.cpp is the following one:

#include "detector_core.h"


int main()
{
	Mat img = imread("13.jpg",IMREAD_GRAYSCALE);
	Mat out;
	double *ans = NULL;
	ellipse_detector(img, 1, -1, ans, out);
	transpose(out, out);
	imwrite("output.jpg",out);
	free(ans);
	waitKey(0);
	return 0;
}

detector_core.h is a code of your detector where I put your code with the ellipse_detector function.

It works so that it detects arc-support lines, combines them into groups but it cannot find initial ellipses and hence no output ellipses, only arcs which look quite reliable.

output

How to fix it so it could provide ellipses?

IaBogdi avatar Oct 02 '19 12:10 IaBogdi

Hey, could you share the entire C++ code so I could have a look at it?

Kakashi4 avatar Nov 17 '19 06:11 Kakashi4

Sure ;)

main.cpp https://pastebin.com/i0AM1njk

detector_core.h : https://pastebin.com/kWDp1LDE

IaBogdi avatar Nov 18 '19 05:11 IaBogdi

Thank you so much, I'll look through it

Kakashi4 avatar Nov 18 '19 06:11 Kakashi4

Hey, I'm having a few problems getting the lapacke header files to be recognized by my visual studio, do you have any idea about it? I already added the lapacke libraries and dlls to my project.

Kakashi4 avatar Nov 18 '19 18:11 Kakashi4

Hi, IaBogdi, Do you have solved the above problem ?

MrYaoLIng avatar Jan 18 '20 12:01 MrYaoLIng

Hi, @IaBogdi , did you manage to solve the problem of not detecting any ellipse?

OnofreMartorell avatar Jan 21 '20 12:01 OnofreMartorell

Dear developer,

I attempted to change the code so it could run on C++. In file generateEllipseCandidates.cpp I replaced mexFunction by the following one:

void ellipse_detector(Mat& img, int edge_process_select, int specified_polarity, double* candidates_out, Mat& out_mat) {
	uchar * inputimg = img.data;
	int imgy, imgx;
	imgy = img.cols;
	imgx = img.rows;
	double *data = (double*)malloc(imgy*imgx * sizeof(double));
	for (int c = 0; c<imgx; c++)
	{
		for (int r = 0; r<imgy; r++)
		{
			data[c + r*imgx] = inputimg[r + c*imgy];
		}
	}
	int n;
	std::vector<std::vector<int> > groups;
	double * coverages;
	int * reg;
	int reg_x;
	int reg_y;
	double* out = mylsd(&n, data, imgx, imgy, &reg, &reg_x, &reg_y);
	groupLSs(out, n, reg, reg_x, reg_y, &groups);
	free(reg);
	calcuGroupCoverage(out, n, groups, coverages);

	printf("The number of output arc-support line segments: %i\n", n);
	printf("The number of arc-support groups:%i\n", groups.size());
	image_double angles;
	if (edge_process_select == 1)
		calculateGradient2(data, imgx, imgy, &angles); //version2, sobel; version 3 canny
	else
		calculateGradient3(data, imgx, imgy, &angles); //version2, sobel; version 3 canny
	PairGroupList * pairGroupList;
	double distance_tolerance = 2;
	printf("Tolerance: %f \n", distance_tolerance);
	double * candidates;
	int  candidates_num;//��ѡ��Բ����
							//rejectShortLines(out,n,&new_n);
	pairGroupList = getValidInitialEllipseSet(out, n, &groups, coverages, angles, distance_tolerance, specified_polarity);
	if (pairGroupList != NULL)
	{
		printf("The number of initial ellipses %i \n", pairGroupList->length);
		generateEllipseCandidates(pairGroupList, distance_tolerance, candidates, &candidates_num);
		printf("The number of ellipse candidates: %i \n", candidates_num);
		candidates_out = (double*) malloc(sizeof(double) * 5 * candidates_num);
		memcpy(candidates_out, candidates, sizeof(double) * 5 * candidates_num);
		//��ѡԲ���(xi,yi,ai,bi,phi_i)', 5 x candidates_num, ���Ƶ�����candidates_out��
		freePairGroupList(pairGroupList);
	}
	else
	{
		candidates_num = 0;
		printf("The number of initial ellipses %i \n", 0);
		candidates_out = (double*)malloc(5 * sizeof(double));
		candidates_out[0] = candidates_out[1] = candidates_out[2] = candidates_out[3] = candidates_out[4] = 0;
	}
	transpose(img, out_mat);
	for (int i = 0; i<n; i++)//draw lines
	{
		Point2d p1(out[8 * i], out[8 * i + 1]), p2(out[8 * i + 2], out[8 * i + 3]);
		line(out_mat, p1, p2, Scalar(255, 0, 0));
	}
	if (candidates_num > 0)//draw ellipses
	{
		for (int i = 0; i<candidates_num; i++)
			ellipse(out_mat, cv::Point((int)candidates_out[i * 5], (int)candidates_out[i * 5 + 1]), cv::Size(candidates_out[i * 5 + 2], candidates_out[i * 5 + 3]), candidates_out[i * 5 + 4] * 180 / M_PI, 0, 360, (Scalar(255, 0, 0)), 1);
	}
	free(data);
	free(coverages);
	free(out);
	free_image_double(angles);

}

and main.cpp is the following one:

#include "detector_core.h"


int main()
{
	Mat img = imread("13.jpg",IMREAD_GRAYSCALE);
	Mat out;
	double *ans = NULL;
	ellipse_detector(img, 1, -1, ans, out);
	transpose(out, out);
	imwrite("output.jpg",out);
	free(ans);
	waitKey(0);
	return 0;
}

detector_core.h is a code of your detector where I put your code with the ellipse_detector function.

It works so that it detects arc-support lines, combines them into groups but it cannot find initial ellipses and hence no output ellipses, only arcs which look quite reliable.

output

How to fix it so it could provide ellipses?

Could be the lapack you link to the program. I tried with lapack (failure, just like you, no initial ellipses), mwlapack (lapack with matlab) this one works, lapack from veclib of macos (works).

xiahaa avatar May 20 '20 15:05 xiahaa

@IaBogdi The pastebin links are dead. Can you upload your code again? Thanks!

Dear developer,

I attempted to change the code so it could run on C++. In file generateEllipseCandidates.cpp I replaced mexFunction by the following one:

void ellipse_detector(Mat& img, int edge_process_select, int specified_polarity, double* candidates_out, Mat& out_mat) {
	uchar * inputimg = img.data;
	int imgy, imgx;
	imgy = img.cols;
	imgx = img.rows;
	double *data = (double*)malloc(imgy*imgx * sizeof(double));
	for (int c = 0; c<imgx; c++)
	{
		for (int r = 0; r<imgy; r++)
		{
			data[c + r*imgx] = inputimg[r + c*imgy];
		}
	}
	int n;
	std::vector<std::vector<int> > groups;
	double * coverages;
	int * reg;
	int reg_x;
	int reg_y;
	double* out = mylsd(&n, data, imgx, imgy, &reg, &reg_x, &reg_y);
	groupLSs(out, n, reg, reg_x, reg_y, &groups);
	free(reg);
	calcuGroupCoverage(out, n, groups, coverages);

	printf("The number of output arc-support line segments: %i\n", n);
	printf("The number of arc-support groups:%i\n", groups.size());
	image_double angles;
	if (edge_process_select == 1)
		calculateGradient2(data, imgx, imgy, &angles); //version2, sobel; version 3 canny
	else
		calculateGradient3(data, imgx, imgy, &angles); //version2, sobel; version 3 canny
	PairGroupList * pairGroupList;
	double distance_tolerance = 2;
	printf("Tolerance: %f \n", distance_tolerance);
	double * candidates;
	int  candidates_num;//��ѡ��Բ����
							//rejectShortLines(out,n,&new_n);
	pairGroupList = getValidInitialEllipseSet(out, n, &groups, coverages, angles, distance_tolerance, specified_polarity);
	if (pairGroupList != NULL)
	{
		printf("The number of initial ellipses %i \n", pairGroupList->length);
		generateEllipseCandidates(pairGroupList, distance_tolerance, candidates, &candidates_num);
		printf("The number of ellipse candidates: %i \n", candidates_num);
		candidates_out = (double*) malloc(sizeof(double) * 5 * candidates_num);
		memcpy(candidates_out, candidates, sizeof(double) * 5 * candidates_num);
		//��ѡԲ���(xi,yi,ai,bi,phi_i)', 5 x candidates_num, ���Ƶ�����candidates_out��
		freePairGroupList(pairGroupList);
	}
	else
	{
		candidates_num = 0;
		printf("The number of initial ellipses %i \n", 0);
		candidates_out = (double*)malloc(5 * sizeof(double));
		candidates_out[0] = candidates_out[1] = candidates_out[2] = candidates_out[3] = candidates_out[4] = 0;
	}
	transpose(img, out_mat);
	for (int i = 0; i<n; i++)//draw lines
	{
		Point2d p1(out[8 * i], out[8 * i + 1]), p2(out[8 * i + 2], out[8 * i + 3]);
		line(out_mat, p1, p2, Scalar(255, 0, 0));
	}
	if (candidates_num > 0)//draw ellipses
	{
		for (int i = 0; i<candidates_num; i++)
			ellipse(out_mat, cv::Point((int)candidates_out[i * 5], (int)candidates_out[i * 5 + 1]), cv::Size(candidates_out[i * 5 + 2], candidates_out[i * 5 + 3]), candidates_out[i * 5 + 4] * 180 / M_PI, 0, 360, (Scalar(255, 0, 0)), 1);
	}
	free(data);
	free(coverages);
	free(out);
	free_image_double(angles);

}

and main.cpp is the following one:

#include "detector_core.h"


int main()
{
	Mat img = imread("13.jpg",IMREAD_GRAYSCALE);
	Mat out;
	double *ans = NULL;
	ellipse_detector(img, 1, -1, ans, out);
	transpose(out, out);
	imwrite("output.jpg",out);
	free(ans);
	waitKey(0);
	return 0;
}

detector_core.h is a code of your detector where I put your code with the ellipse_detector function.

It works so that it detects arc-support lines, combines them into groups but it cannot find initial ellipses and hence no output ellipses, only arcs which look quite reliable.

output

How to fix it so it could provide ellipses?

Hi, My dear friend~ Can I get your C++ code about it now?

Mickeyyyang avatar Mar 27 '21 06:03 Mickeyyyang

@IaBogdi Finally, I think I get the cause. If anybody is using LAPACKE, then the following line of code is NOT correct: LAPACKE_dggev(xxxx) It should not be ROW_MAJOR, but COL_MAJOR.

xiahaa avatar May 06 '22 03:05 xiahaa