2017-10-09 60 views
0

我看到在SE和其他地方计算交点&联合的一些帖子,但我有两个任意的椭圆:旋转,翻译,不同的半长轴& semiminor轴。计算两个旋转椭圆的交集/并集?

有没有人有建议计算他们的交叉口工会值?

我正在使用OpenCV & Python,因为它值得。

如果我/我们不能想出任何聪明和快速的东西,那么我将使用基于掩码的方法,我只需定义一个零数组,然后用1填充第一个定义的区域椭圆,并为第二个椭圆加1,然后我就知道联合是数组非零的任何地方,并且交集将在数组为2的任何地方。但是这听起来很慢。

编辑:再。 “听起来有点慢”:因为我想每秒钟评估一次这个“数字”,所以我更喜欢一个分析方程来计算它(例如,像非旋转矩形一样),而不仅仅是一个基于像素的遮罩实现。

+2

我真的不看你如何能做得比你的计划更快。我唯一能想到的是,你不需要计算整个图像上的掩码,而只需要在椭圆被绑定的矩形中......而且我会用布尔掩码/逻辑去使用,而不是使用0, 1,2值。 – Julien

+0

你应该使用该方法,但是如果你想要,你可以重载'__and__'和'__or__'运算符,所以你可以使用'&'和'|' – 0TTT0

+0

@ 0TTT0'&'和'|'已经适用于布尔口罩... – Julien

回答

0

如果你不想做额外的面具,你必须实现布尔函数,如果在椭圆形(与一般的椭圆式用法):

https://math.stackexchange.com/a/434482/

然后你可以彩色像素只有满足该等式。下面我附C++例子(我应该很容易将其转换为蟒蛇):

bool ifInEllipse(cv::Size _axes, float _angle, cv::Point _center, cv::Point _point) 
{ 

_angle =CV_PI/180*_angle; 


float cosine = cos(_angle); 
float sine = sin(_angle); 


float res1 = (_point.x - _center.x)*cosine + (_point.y - _center.y)*sine; 
res1 = res1*res1; 
float res2 = (_point.x - _center.x)*sine - (_point.y - _center.y)*cosine; 
res2 = res2*res2; 

float a = _axes.width; 
float b = _axes.height; 
return ((res1/(a*a)) + (res2/(b*b))) < 1; 
} 

与实施例一用法:

cv::Mat A1,A2, B1,B2, AA,BB; 
A1 = cv::Mat::zeros(500, 500, CV_8UC1); 
A2 = cv::Mat::zeros(500, 500, CV_8UC1); 

cv::Point center1(200, 200); 
cv::Size axes1(100, 50); 
float angle1 =30; 

cv::ellipse(A1, center1, axes1, angle1, 0, 360,cv::Scalar(255,255,255),-1); 


B1 = cv::Mat::zeros(500, 500, CV_8UC1); 
B2 = cv::Mat::zeros(500, 500, CV_8UC1); 
for(int i=0;i<500;i++) 
{ 
    for(int j=0;j<500;j++) 
    { 
     if(ifInEllipse(axes1,angle1,center1,cv::Point(i,j))) 
     { 
      B1.at<uchar>(j, i) = 255; 
     } 
    } 
} 

cv::Point center2(350, 300); 
cv::Size axes2(60, 120); 
float angle2 = -45; 


cv::ellipse(A2, center2, axes2, angle2, 0, 360, cv::Scalar(255, 255, 255), -1); 


B2 = cv::Mat::zeros(500, 500, CV_8UC1); 
for (int i = 0; i<500; i++) 
{ 
    for (int j = 0; j<500; j++) 
    { 
     if (ifInEllipse(axes2, angle2, center2, cv::Point(i, j))) 
     { 
      B2.at<uchar>(j, i) = 255; 
     } 
    } 
} 


AA = cv::Mat::zeros(500, 500, CV_8UC1); 
BB = cv::Mat::zeros(500, 500, CV_8UC1); 

cv::bitwise_and(A1, A2,AA); 



for (int i = 0; i<500; i++) 
{ 
    for (int j = 0; j<500; j++) 
    { 
     if (ifInEllipse(axes1, angle1, center1, cv::Point(i, j))) 
     { 
      if (ifInEllipse(axes2, angle2, center2, cv::Point(i, j))) 
      { 
       BB.at<uchar>(j, i) = 255; 
      } 
     } 
    } 
} 

结果:

enter image description here