Pindai Garis untuk Filter Partikel dengan openGL

Saya menerapkan Filter Partikel untuk pelacakan kubus 3D di C++.

Saya menghadapi masalah yang signifikan ketika menetapkan bobot untuk partikel, karena bobot didasarkan pada kesalahan jarak (dalam hal ini) antara titik sampel dan piksel (dijelaskan di bawah).

Saat ini saya bisa mendapatkan aliran video dari kamera di laptop saya, menampilkannya di layar dan menggambar partikel di atasnya. Saya juga dapat mengekstrak tepi objek yang terdeteksi dari kamera dan menemukan koordinat konturnya.

Tangkapan layar

Berikut cara mendeteksi koordinat kontur:

vector<vector<Point>> detectContours(Mat image){

    vector<vector<Point>> contoursEdges;
    vector<Vec4i> hierarchy;

    Mat clone;
    clone = image.clone();

    Mat contours;
    GaussianBlur(clone, contours, Size(5,5), 1);

    cvtColor(contours, contours, CV_BGR2GRAY);

    Mat cannyEdges;
    Canny(contours, cannyEdges, 50, 100, 3);

    try{
        findContours(cannyEdges, contoursEdges, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point(0,0));
    }catch(exception e){
        printf("Exception: Contours cannot be found!!!\n");
    }

    return contoursEdges;
}

Namun, seperti yang saya katakan, partikel digambar di atas aliran video (seperti yang ditunjukkan pada cuplikan layar). Setiap bidang dibagi menjadi sebuah kotak.

Inilah cara melakukannya:

void DrawBox(GLfloat fWidth,GLfloat fHeight,GLfloat fDepth,GLint wslices,GLint dslices,GLint stacks, GLfloat scanSize)
{

glPushAttrib(GL_POLYGON_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT) ;

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) ;

glEnable(GL_CULL_FACE); // allow only front surfaces to be visible

int iTopButtonQuads = wslices * dslices * 2;
int iLeftRightQuads = dslices * stacks * 2;
int iFrontBackQuads = wslices * stacks * 2;

float* pfVertices = new float[(iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 3 * 4];
float* pfColors = new float[(iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 3 * 4];
float* pfNormals = new float[(iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 3 * 4];

int iVertexIndex = 0;

GLfloat Xstep = fWidth / wslices;
GLfloat Ystep = fHeight / stacks;
GLfloat Zstep = fDepth / dslices;

GLfloat firstX = fWidth / 2.0f;
GLfloat firstY = fHeight / 2.0f;
GLfloat firstZ = fDepth / 2.0f;

GLfloat currX = 0.0f;
GLfloat currY = 0.0f;
GLfloat currZ = 0.0f;

GLfloat x_status = 0.0f;
GLfloat y_status = 0.0f;
GLfloat z_status = 0.0f;

// the bottom and the top of the box
for (currZ = -firstZ, z_status = 0.0f; currZ < firstZ - Zstep / 2.0f; currZ += Zstep, z_status += Zstep)
{
    for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
    {
        int iCurrentIndex = iVertexIndex * 3 * 4;

        float pfNormal[3] = { 0.0f, -1.0f, 0.0f };

        memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

        float pfColor[3] = { 1.0f, 0.0f, 0.0f };

        memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

        float pfVertex0[3] = {currX,-firstY,currZ};
        float pfVertex1[3] = {currX + Xstep,-firstY,currZ};
        float pfVertex2[3] = {currX + Xstep,-firstY,currZ + Zstep};
        float pfVertex3[3] = {currX,-firstY,currZ + Zstep};

        memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

        iVertexIndex++;
    }

    for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
    {
        int iCurrentIndex = iVertexIndex * 3 * 4;

        float pfNormal[3] = { 0.0f, 1.0f, 0.0f };

        memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

        float pfColor[3] = { 0.0f, 1.0f, 0.0f };

        memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

        float pfVertex0[3] = {currX + Xstep,firstY,currZ + Zstep};
        float pfVertex1[3] = {currX + Xstep,firstY,currZ};
        float pfVertex2[3] = {currX,firstY,currZ};
        float pfVertex3[3] = {currX,firstY,currZ + Zstep};

        memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

        iVertexIndex++;
    }
}

// the front and the back of the box
for (currY = -firstY, y_status = 0.0f; currY < firstY - Ystep / 2.0f ; currY += Ystep, y_status += Ystep)
{
    for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
    {
        int iCurrentIndex = iVertexIndex * 3 * 4;

        float pfNormal[3] = { 0.0f, 0.0f, 1.0f };

        memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

        float pfColor[3] = { 0.0f, 0.0f, 1.0f };

        memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

        float pfVertex0[3] = {currX,currY,firstZ};
        float pfVertex1[3] = {currX + Xstep,currY,firstZ};
        float pfVertex2[3] = {currX + Xstep,currY + Ystep,firstZ};
        float pfVertex3[3] = {currX,currY + Ystep,firstZ};

        memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

        iVertexIndex++;
    }

    for (currX = -firstX, x_status = 0.0f; currX < firstX - Xstep / 2.0f; currX += Xstep, x_status += Xstep)
    {
        int iCurrentIndex = iVertexIndex * 3 * 4;

        float pfNormal[3] = { 0.0f, 0.0f, -1.0f };

        memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

        float pfColor[3] = { 0.0f, 1.0f, 1.0f };

        memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

        float pfVertex0[3] = {currX + Xstep,currY + Ystep,-firstZ};
        float pfVertex1[3] = {currX + Xstep,currY,-firstZ};
        float pfVertex2[3] = {currX,currY,-firstZ};
        float pfVertex3[3] = {currX,currY + Ystep,-firstZ};

        memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

        iVertexIndex++;
    }
}

// Right side and the left side of the box
for (currY = -firstY, y_status = 0.0f; currY < firstY - Ystep / 2.0f; currY += Ystep, y_status += Ystep)
{
    for (currZ = -firstZ, z_status = 0.0f; currZ < firstZ - Zstep / 2.0f; currZ += Zstep, z_status += Zstep)
    {
        int iCurrentIndex = iVertexIndex * 3 * 4;

        float pfNormal[3] = { 1.0f, 0.0f, 0.0f };

        memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

        float pfColor[3] = { 1.0f, 0.0f, 1.0f };

        memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

        float pfVertex0[3] = {firstX,currY,currZ};
        float pfVertex1[3] = {firstX,currY + Ystep,currZ};
        float pfVertex2[3] = {firstX,currY + Ystep,currZ + Zstep};
        float pfVertex3[3] = {firstX,currY,currZ + Zstep};

        memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

        iVertexIndex++;
    }

    for (currZ = -firstZ, z_status = 0.0f; currZ < firstZ - Zstep / 2.0f; currZ += Zstep, z_status += Zstep)
    {
        int iCurrentIndex = iVertexIndex * 3 * 4;

        float pfNormal[3] = { -1.0f, 0.0f, 0.0f };

        memcpy(pfNormals + iCurrentIndex, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 3, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 6, pfNormal, 3 * 4);
        memcpy(pfNormals + iCurrentIndex + 9, pfNormal, 3 * 4);

        float pfColor[3] = { 1.0f, 1.0f, 0.0f };

        memcpy(pfColors + iCurrentIndex, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 3, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 6, pfColor, 3 * 4);
        memcpy(pfColors + iCurrentIndex + 9, pfColor, 3 * 4);

        float pfVertex0[3] = {-firstX,currY,currZ};
        float pfVertex1[3] = {-firstX,currY,currZ + Zstep};
        float pfVertex2[3] = {-firstX,currY + Ystep,currZ + Zstep};
        float pfVertex3[3] = {-firstX,currY + Ystep,currZ};

        memcpy(pfVertices + iCurrentIndex, pfVertex0, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 3, pfVertex1, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 6, pfVertex2, 3 * 4);
        memcpy(pfVertices + iCurrentIndex + 9, pfVertex3, 3 * 4);

        iVertexIndex++;
    }
}

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

glColorPointer(3, GL_FLOAT, 0, (void*)pfColors);
glNormalPointer(GL_FLOAT, 0, (void*)pfNormals);
glVertexPointer(3, GL_FLOAT, 0, (void*)pfVertices);

glDrawArrays(GL_QUADS, 0, (iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 4);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);

// Get coord of first vertex
float fMinX = pfVertices[0];
float fMinY = pfVertices[1];
float fMinZ = pfVertices[2];

float fMaxX = pfVertices[0];
float fMaxY = pfVertices[1];
float fMaxZ = pfVertices[2];

for (int iVertexIndex = 0; iVertexIndex < (iTopButtonQuads + iLeftRightQuads + iFrontBackQuads) * 4; iVertexIndex++)
{
    int iCurrentIndex = iVertexIndex * 3; // (x y z) per vertex

    if (pfVertices[iCurrentIndex] < fMinX)
        fMinX = pfVertices[iCurrentIndex];

    if (pfVertices[iCurrentIndex + 1] < fMinY)
        fMinY = pfVertices[iCurrentIndex + 1];

    if (pfVertices[iCurrentIndex + 2] < fMinZ)
        fMinZ = pfVertices[iCurrentIndex + 2];

    if (pfVertices[iCurrentIndex] > fMaxX)
        fMaxX = pfVertices[iCurrentIndex];

    if (pfVertices[iCurrentIndex + 1] > fMaxY)
        fMaxY = pfVertices[iCurrentIndex + 1];

    if (pfVertices[iCurrentIndex + 2] > fMaxZ)
        fMaxZ = pfVertices[iCurrentIndex + 2];
}

// Create an axes aligned bounding box 
// by simply drawing inflated min-maxes, that we collect
// example of using indexed primitives

glDisable(GL_CULL_FACE);

GLfloat vertices[] = {
    fMinX - scanSize, fMaxY + scanSize, fMaxZ + scanSize,
    fMaxX + scanSize, fMaxY + scanSize, fMaxZ + scanSize,
    fMaxX + scanSize, fMinY - scanSize, fMaxZ + scanSize,
    fMinX - scanSize, fMinY - scanSize, fMaxZ + scanSize,
    fMinX - scanSize, fMaxY + scanSize, fMinZ - scanSize,
    fMaxX + scanSize, fMaxY + scanSize, fMinZ - scanSize,
    fMaxX + scanSize, fMinY - scanSize, fMinZ - scanSize,
    fMinX - scanSize, fMinY - scanSize, fMinZ - scanSize
};

GLint indices[] = {
    0, 1, 2, 3,
    4, 5, 1, 0,
    3, 2, 6, 7,
    5, 4, 7, 6,
    1, 5, 6, 2,
    4, 0, 3, 7 
};

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

glEnableClientState(GL_VERTEX_ARRAY);

glVertexPointer(3, GL_FLOAT, 0, (void*)vertices);

glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, (void*)indices);

glDisableClientState(GL_VERTEX_ARRAY);

glEnable(GL_CULL_FACE);

delete [] pfVertices;
delete [] pfNormals;
delete [] pfColors;

glPopAttrib() ;
} 

Masalah saya sekarang adalah sebagai berikut:

  • Kumpulkan hanya titik batas dari keenam kisi untuk setiap partikel (titik sampel)
  • Gambarlah garis pindaian dari setiap titik tersebut dengan ukuran, katakanlah, 20 piksel di kedua arah dari titik tersebut

Poin kedua diperlukan untuk mencari jarak antara titik sampel dan tepi yang terdeteksi seperti yang ditunjukkan pada gambar di bawah.

Ini adalah versi 2D yang disederhanakan. Setiap garis hijau mewakili garis pemindaian dan 'Dist' adalah jarak antara titik sampel dan piksel yang ditemukan di suatu tepi

Jika seseorang dapat menyarankan solusi bagaimana menemukan jarak atau sebaiknya memposting beberapa cuplikan kode, itu akan sangat dihargai.


person VnC    schedule 15.10.2015    source sumber