如何确定图像中多边形的面积

时间:2014-11-27 10:20:32

标签: c++ math image-processing polygon area

如果我有一个凸多边形顶点,那么我在标准公式中的面积计算不准确。

(对于simiplicity)如果我有3x3平方,并且顶点是(1,1)(1,3)(3,3)(3,1)

enter image description here

通过此处描述的多边形面积计算方法

enter image description here

并将总和除以2得到面积。

因此,对于上面的3 x 3数据,我们将区域设为4而不是9。

enter image description here

这种情况正在发生,因为顶点不是点而是像素

这是相应的代码。坐标是循环的。

int X[] = { 1, 1, 3, 3, 1};
int Y[] = { 1, 3, 3, 1, 1};
double Sum1 = 0;
double Sum2 = 0;
int numElements = 5;

    for (int k = 0; k < numElements-1; k++)
    {
        Sum1 += X[k] * Y[k + 1];
        Sum2 += Y[k] * X[k + 1];
    }

    double area = std::abs((double)(Sum1 - Sum2))/2;

对于方形,我们可以对宽度和高度做+1,并使区域正确。但是图像中的不规则多边形怎么样? 我希望这个问题有道理。

2 个答案:

答案 0 :(得分:1)

如果您不想将像素角作为顶点,请考虑下一个方法(适用于简单的图形 - 所有凸面图形,一些凹面图形):

enter image description here

在每个右边框像素的右下角,右下角像素的右下角,在每个右边框像素的右侧添加额外的假像素。这里灰色像素是初始的,浅蓝色像素是假的。

答案 1 :(得分:1)

可以按以下步骤计算面积:

1)获取顶点之间的像素

2)按x坐标(或y坐标)

对像素进行排序

3)获取特定x (或y)值的最小和最大y坐标(或x)之间的差值,并将差值加1

4)总结差异

注意:区域可能会有所不同(如果多边形中有斜边),具体取决于所选的线条绘制方法

int compare(const void * a, const void * b)
{
  return (((Point*)a)->x() - ((Point*)b)->x());
}


double CalculateConvexHullArea(vector<int> ConvexHullX, vector<int> ConvexHullY)
{
    float Sum1 = 0;
    float Sum2 = 0;
    std::vector<Point> FillPoints;


        for (int k = 0; k < ConvexHullX.size() - 1; k++)
        {
            drawLine(ConvexHullX[k], ConvexHullX[k+1], ConvexHullY[k], ConvexHullY[k+1], FillPoints);
        }

        //sorting coordinates
        qsort(FillPoints.data(), FillPoints.size(), sizeof(Point), compare);

        double area = 0;
        int startY = FillPoints[0].y(), endY = FillPoints[0].y();
        int currX = FillPoints[0].x();


        // traversing x and summing up diff of min and max Y
        for (int cnt = 0; cnt < FillPoints.size(); cnt++)
        {
            if (FillPoints[cnt].x() == currX)
            {
                startY = startY > FillPoints[cnt].y() ? FillPoints[cnt].y() : startY;
                endY = endY < FillPoints[cnt].y() ? FillPoints[cnt].y() : endY;
            }
            else
            {
                int diffY = endY - startY + 1;
                area += diffY;
                currX = FillPoints[cnt].x();
                startY = endY = FillPoints[cnt].y();
            }
        }

        return area + endY - startY + 1;
}