1

对于一个学校项目,我的小组正在使用 OpenCV 来捕获视频。从这些(自上而下)图像中,提取对象的位置并将其转换为点列表。然后使用http://code.google.com/p/poly2tri/对这些点进行三角测量(以克服可能的非凸对象的问题)。然后,使用三角地窗格的坐标,我们使用 freeglut 在 3D 中绘制对象。(侧面和顶部窗格使用地面窗格坐标计算)。我们遇到的问题是,当我们删除旧的点列表时,应用程序会随机崩溃。有时 1 秒后,有时 30 秒后,有时几分钟后。我们得到的错误是“访问冲突写入位置 0xCCCCCCCC”

我们的代码:

void WorldLayoutBuilder::update()
{
pointList.clear();

// Capture image
<code to capture image and get countours>

for(size_t i = 0; i < contours.size(); i++)
{
    if(contours[i].size() > 50)
    {
        approxPolyDP(contours[i], approxShape, cv::arcLength(cv::Mat(contours[i]), true)*0.04, true);
        drawContours(drawing, contours, i, cv::Scalar(255, 0, 0), 0);

        std::vector<Point> newObject;

        for(size_t j = 0; j < contours[i].size(); j++)
        {
            cv::Point newPoint = contours[i][j];    
            newObject.push_back(Point((float) newPoint.x / 100, 0.0f,(float) newPoint.y / 100));
        }

        pointList.push_back(newObject);
    }
}

ObjectCreator3D::createObjects(&pointList);
contours.clear();

<code to release images, etc>
}

这会捕获图像,检索对象的坐标,然后调用 ObjectCreator3D::createObjects():

void ObjectCreator3D::createObjects(std::list<std::vector<Point>>* inputList)
{
std::list<WorldObject>* tempObjects = new std::list<WorldObject>;

for(std::vector<Point>&pointObject : *inputList)
{                       
    WorldObject worldObject(&pointObject);
    tempObjects->push_back(worldObject);
}

DataStorage::getInstance()->setObjects(tempObjects);
}

所有对象都变成 WorldObjects:

#include <list>
#include <iostream>
#include <GL/glut.h>
#include <GL/freeglut.h>
#include <time.h>

#include "WorldObject.h"
#include "Point.h"

//Constant height - adjustable/randomized solution is partially implemented in the     constructor.
const float WorldObject::HEIGHT = 5.0f;

template <class C> void FreeClear(C & cntr)
{
for(typename C::iterator it = cntr.begin(); it != cntr.end(); ++it)
{
    delete * it;
}
cntr.clear();
}

WorldObject::WorldObject(std::vector<Point>* pointList)
{
//TODO, when we have time. Seems difficult because height will change each update...
/*srand (time(NULL));
float fGeneratedY = (rand() % 20 + 2) / 2.0f;*/

cdt = nullptr;

for (Point &point : *pointList) 
    //point.setY(fGeneratedY);
    point.setY(HEIGHT);

this->pointList = pointList;
}

WorldObject::~WorldObject()
{
//Cleanup
delete cdt;
FreeClear(polyPoints);
}

/*
Author Tim Cocu & Bas Rops
Function for drawing the WorldObject
*/
void WorldObject::draw()
{
glPushMatrix();

glColor3f(0.8f, 0.8f, 0.8f);

//Calculate our bottom pane
calculateTriangles();

//BOTTOM PANE
for (unsigned int i = 0; i < calculatedTriangles.size(); i++)
{
    p2t::Triangle& t = *calculatedTriangles[i];
    p2t::Point& a = *t.GetPoint(0);
    p2t::Point& b = *t.GetPoint(1);
    p2t::Point& c = *t.GetPoint(2);

    glBegin(GL_TRIANGLES);
        glNormal3f(0, -1, 0);
        glVertex3f((GLfloat)a.x, (GLfloat)0.0f, (GLfloat)a.y);
        glVertex3f((GLfloat)b.x, (GLfloat)0.0f, (GLfloat)b.y);
        glVertex3f((GLfloat)c.x, (GLfloat)0.0f, (GLfloat)c.y);
    glEnd();
}

//TOP PANE
for (unsigned int i = 0; i < calculatedTriangles.size(); i++)
{
    p2t::Triangle& t = *calculatedTriangles[i];
    p2t::Point& a = *t.GetPoint(0);
    p2t::Point& b = *t.GetPoint(1);
    p2t::Point& c = *t.GetPoint(2);

    glBegin(GL_TRIANGLES);
        glNormal3f(0, 1, 0);
        glVertex3f((GLfloat)a.x, (GLfloat)HEIGHT, (GLfloat)a.y);
        glVertex3f((GLfloat)b.x, (GLfloat)HEIGHT, (GLfloat)b.y);
        glVertex3f((GLfloat)c.x, (GLfloat)HEIGHT, (GLfloat)c.y);
    glEnd();
}

glColor3f(1.0f, 1.0f, 1.0f);

//SIDE PANES
for(std::size_t iPaneCounter = 0; iPaneCounter < pointList->size(); iPaneCounter++)
{
    Point firstPoint = (*pointList)[iPaneCounter];
    Point secondPoint (0.0f, 0.0f, 0.0f);

    if(iPaneCounter + 1 < pointList->size())
        secondPoint.set((*pointList)[iPaneCounter + 1].getX(), (*pointList)[iPaneCounter + 1].getY(), (*pointList)[iPaneCounter + 1].getZ() );
    else
        secondPoint.set((*pointList)[0].getX(), (*pointList)[0].getY(), (*pointList)[0].getZ());

    glBegin(GL_POLYGON);
        float fNormalX = (firstPoint.getY() * secondPoint.getZ()) - (firstPoint.getZ() * secondPoint.getY());
        float fNormalY = -((secondPoint.getZ() * firstPoint.getX()) - (secondPoint.getX() * firstPoint.getZ()));
        float fNormalZ = (firstPoint.getX() * secondPoint.getY()) - (firstPoint.getY() * secondPoint.getX());
        glNormal3f(fNormalX, fNormalY, fNormalZ);

        glVertex3f(firstPoint.getX(), 0.0f, firstPoint.getZ());
        glVertex3f(secondPoint.getX(), 0.0f, secondPoint.getZ());
        glVertex3f(secondPoint.getX(), secondPoint.getY(), secondPoint.getZ());
        glVertex3f(firstPoint.getX(), firstPoint.getY(), firstPoint.getZ());
    glEnd();
}
}

/*
Calculates triangles that make a ground or top pane. Used for calculating possible     non-convex objects
*/
void WorldObject::calculateTriangles()
{
//Empty the polyPoints list
if(polyPoints.size() > 0)
    FreeClear(polyPoints);

//Convert our Points to p2t::Points
for(std::size_t iBottomIndex = 0; iBottomIndex < pointList->size(); iBottomIndex++)
    polyPoints.push_back(new p2t::Point((*pointList)[iBottomIndex].getX(), (*pointList)[iBottomIndex].getZ()));

if(cdt == nullptr)
    //Create CDT (Constrained Delaunay Triangulation) and add primary polyPoints
    //NOTE: polyPoints must be a simple polygon. The polyPoints' points constitute constrained edges. No repeating points are allowed!
    cdt = new p2t::CDT(polyPoints);

//Turn our polyPoints into p2t::Triangles
cdt->Triangulate();

//Set the triangles to use for drawing
calculatedTriangles = cdt->GetTriangles();
}

/*
Retrieve a pointer to a list of Points
*/
std::vector<Point>* WorldObject::getPoints()
{
return pointList;
}

/*
Retrieve a pointer to a list of p2t::Triangles
*/
std::vector<p2t::Triangle*> WorldObject::getCalculatedTriangles()
{
return calculatedTriangles;
}

当所有 WorldObjects 被创建后,它们被存储在 DataStorage 中,DataStorage::getInstance()->setObjects() 被调用:

void DataStorage::setObjects(std::list<WorldObject>* objectList)
{
delete this->objectList;
this->objectList = objectList;
}

应用程序似乎在删除 this->objectList 时崩溃;在 setObjects() 中,所以我们认为应用程序正在尝试删除他无法删除的内容。

任何帮助将不胜感激,我们已经为此工作了几天

4

1 回答 1

3

在这里,您将指向列表拥有的对象的指针传递给 的构造函数WorldObject

for(std::vector<Point>&pointObject : *inputList)
{                       
  WorldObject worldObject(&pointObject);
  tempObjects->push_back(worldObject);
}

WorldObject你存储指针:

//Default Constructor
WorldObject::WorldObject(std::vector<Point>* pointList)
{
  float fGeneratedY = (rand() % 20 + 2) / 2.0f;*/

  cdt = nullptr;

  for (Point &point : *pointList) 
    point.setY(HEIGHT);

  this->pointList = pointList;
}

Which means WorldObject::pointList is only valid so long as the std::list which you constructed your WorldObjects from is still around. (After that, the result is undefined -- it could work, it could crash, it could format your hard drive and leak your identity to Texas).

If you insist on working with raw pointers, you as programmer are responsible for checking and keeping track of the lifetime of every single pointer. This is error prone and will cause random crashes that you will find difficult to track down.

Stop using raw pointers. Instead, if an object owns a resource, store it in a std::unique_ptr<>. If you want the same resource to be shared by multiple objects, use std::shared_ptr and std::weak_ptr, unless the lifetime of all but one of these objects is much, much shorter than the others in a guaranteed way.

于 2013-05-28T10:00:43.663 回答