コード例 #1
0
double MotionGraph::distance(int ma, int mb, int i, int j, double *theta, double *x0, double *z0)
{
    int k = numBlendingFrames;

    Skeleton *skeleton = library->getSkeleton();
    Motion *motionA = library->getMotion(ma);
    Motion *motionB = library->getMotion(mb);

    if (skeleton == NULL || motionA == NULL || motionB == NULL)
    {
        printf("Error: in distance().\n");
        exit(-1);
    }

    PointCloud **pcListA = new PointCloud *[k];
    PointCloud **pcListB = new PointCloud *[k];
    for (int f = i, ii = 0; f < i + k; f++, ii++)
    {
        skeleton->setPosture(*(motionA->GetPosture(f)));
        pcListA[ii] = new PointCloud(skeleton);
    }
    for (int f = j - k + 1, ii = 0; f < j + 1; f++, ii++)
    {
        skeleton->setPosture(*(motionB->GetPosture(f)));
        pcListB[ii] = new PointCloud(skeleton);
    }

    PointCloud pcA(&pcListA[0], k);
    PointCloud pcB(&pcListB[0], k);
    double dist = distance(&pcA, &pcB, theta, x0, z0);

    for (int i = 0; i < k; i++)
        delete pcListA[i];
    for (int i = 0; i < k; i++)
        delete pcListB[i];
    delete [] pcListA;
    delete [] pcListB;

    return dist;
}
コード例 #2
0
void MotionGraph::genGraph()
{
    int k = numBlendingFrames;
    int restPoseIdx = 0;                                            // rest pose motion idx
    restLabel = 0;

    int numMotions = library->getNumMotions();

    std::vector< std::vector<int> > nodeId;            // nodeId[motionIdx][frameIdx]
    for (int m = 0; m < numMotions; m++)
    {
        nodeId.push_back(std::vector<int>());
        for (int f = 0; f < library->getMotion(m)->GetNumFrames(); f++)
            nodeId[m].push_back(-1);                                        // -1 := not a node
        nodeId[m][0] = 1;                                                   // first frame
        //nodeId[m][nodeId[m].size() - 1] = 1;                                // last frame

        // transition point to the rest pose
        int f = nodeId[m].size() - k;
        if (f >= 0)
            nodeId[m][f] = 1;
    }
    // rest pose
    if ((int)nodeId[restPoseIdx].size() >= k)
        nodeId[restPoseIdx][k - 1] = 1;

    std::vector< std::vector< std::vector<WindowPair> > > candidates;       // [motionIdxA][motionIdxB][pairIdx]
    for (int ma = 0; ma < numMotions; ma++)
    {
        candidates.push_back(std::vector< std::vector<WindowPair> >());
        for (int mb = 0; mb < numMotions; mb++)
        {
            candidates[ma].push_back(std::vector<WindowPair>());
        }
    }

    // load candidates
    printf("Loading transition candidates... ");
    std::ifstream ifs;
    ifs.open("./mocap_data/candidates.txt", std::ios::in);
    char buf[256];
    ifs >> buf;                             // #numMotions
    int nmotions;
    ifs >> nmotions;
    double threshold = 100.0;
    int minCandidateCount = 50;

    for (int ma = 0; ma < nmotions; ma++) for (int mb = 0; mb < nmotions; mb++)
    {
        ifs >> buf;                         // #motionIndex
        int motionIdxA, motionIdxB;
        ifs >> motionIdxA >> motionIdxB;
        //printf("motionIndex: %d, %d\n", motionIdxA, motionIdxB);
        ifs >> buf;                         // #motionName
        ifs >> buf;                         // motionNameA
        ifs >> buf;                         // motionNameB
        ifs >> buf;                         // #numFrames
        int numFramesA, numFramesB;
        ifs >> numFramesA >> numFramesB;
        //printf("numFrames: %d, %d\n", numFramesA, numFramesB);
        ifs >> buf;                         // #minListSize
        int minListSize;
        ifs >> minListSize;
        ifs >> buf;                         // #i
        ifs.getline(buf, sizeof(buf));      // j distance theta x0 z0
        
        int count = 0;
        for (int ii = 0; ii < minListSize; ii++)
        {
            int i, j;
            double dist;
            double theta, x0, z0;
            ifs >> i >> j >> dist >> theta >> x0 >> z0;

            if (j > (int)nodeId[mb].size() - k)     // later than last transition point
                continue;

            // check threshold & conditions
            if (dist > threshold &&
                (count > minCandidateCount ||
                 j > numFramesB / 2))
                //count > minListSize / 20)
                continue;
            count++;

            WindowPair pair;
            pair.i = i;
            pair.j = j;
            pair.dist = dist;
            pair.theta = theta;
            pair.x0 = x0;
            pair.z0 = z0;
            candidates[ma][mb].push_back(pair);

            nodeId[ma][i] = 1;
            nodeId[mb][j] = 1;
        }
    }
    ifs.close();

    printf("done.\n");

    /*for (int aa = 0; aa < numMotions; aa++)
        for (int bb = 0; bb < numMotions; bb++)
        {
            printf("motion(%d, %d): %d\n", aa, bb, candidates[aa][bb].size());
            for (size_t ii = 0; ii < candidates[aa][bb].size(); ii++)
            {
                WindowPair &p = candidates[aa][bb][ii];
                printf("%d %d %lf %lf %lf %lf\n", p.i, p.j, p.dist, p.theta, p.x0, p.z0);
            }
        }
    */

    printf("Construcing graph...\n");

    int numNodes = 0;
    int numEdges = 0;

    // construct nodes and edges within motions
    for (int m = 0; m < numMotions; m++)
    {
        int lastNode = -1;
        int count = 0;
        for (int f = 0; f < (int)nodeId[m].size(); f++)
            if (nodeId[m][f] >= 0)
            {
                // form a new node
                nodeId[m][f] = numNodes++;

                //printf("node(%d): %d, %d\n", nodeId[m][f], m, f);

                Node node;
                node.id = nodeId[m][f];
                node.motionIdx = m;
                node.frameIdx = f;
                node.label = m;                 // use motion idx as label
                nodes.push_back(node);
                
                count++;

                if (lastNode != -1)             // not the first node of the motion
                {
                    // construct an edge fram last node to current node
                    int id = numEdges++;
                    int src = nodeId[m][lastNode];
                    int dst = nodeId[m][f];
                    addEdge(id, src, dst, 0.0, 0.0, 0.0, f - lastNode);
                    nodes[src].link.push_back(id);
                }
                lastNode = f;
            }

        printf("Motion(%d): total nodes: %d\n", m, count);
    }
        
    // construct edges crossing two motions
    for (int ma = 0; ma < numMotions; ma++)
    {
        for (int mb = 0; mb < numMotions; mb++)
        {
            for (size_t ii = 0; ii < candidates[ma][mb].size(); ii++)
            {
                WindowPair &pair = candidates[ma][mb][ii];

                // construct an edge from A(i) to B(j)
                int id = numEdges++;
                int src = nodeId[ma][pair.i];
                int dst = nodeId[mb][pair.j];
                addEdge(id, src, dst, pair.theta, pair.x0, pair.z0, k - 1);
                nodes[src].link.push_back(id);
            }
        }
    }

    // construct edges from the end of motions to the rest pose
    if ((int)nodeId[restPoseIdx].size() >= k)
    {
        for (int m = 0; m < numMotions; m++)
        {
            double theta, x0, z0;
            distance(m, restPoseIdx, nodeId[m].size() - k, k - 1, &theta, &x0, &z0);
            
            int id = numEdges++;
            int src = nodeId[m][nodeId[m].size() - k];
            int dst = nodeId[restPoseIdx][k - 1];

            addEdge(id, src, dst, theta, x0, z0, k - 1, 1);
            nodes[src].link.push_back(id);
        }
    }

    // test: dump
    for (size_t eid = 0; eid < edges.size(); eid++)
    {
        Edge &e = edges[eid];
        int srcMotion = nodes[e.src].motionIdx;
        int dstMotion = nodes[e.dst].motionIdx;
        int srcFrame = nodes[e.src].frameIdx;
        int dstFrame = nodes[e.dst].frameIdx;
        //printf("edge(%d): %d(%d) --> %d(%d)\n", eid, srcMotion, srcFrame, dstMotion, dstFrame);
    }

    printf("Construcing graph... done.\n");

    ////////////////////////////////////////////////////////////////////////////

    printf("Constructing shortest path table... ");

    int numLabels = numMotions;         // can be different

    for (int dstLabel = 0; dstLabel < numLabels; dstLabel++)
    {
        // find shortest path to a certain label
        std::vector<int> dist;
        std::vector<int> next;
        for (size_t i = 0; i < nodes.size(); i++)
        {
            int initDist = 999999999;
            if (nodes[i].label == dstLabel)
                initDist = 0;
            dist.push_back(initDist);
            next.push_back(-1);
        }

        // Bellman-Ford
        for (int i = 0; i < (int)nodes.size() - 1; i++)
        {
            for (int j = 0; j < (int)edges.size(); j++)
            {
                int src = edges[j].src;
                int dst = edges[j].dst;
                if (dist[src] > dist[dst] + edges[j].length)
                {
                    dist[src] = dist[dst] + edges[j].length;
                    next[src] = j;
                }
            }
        }

        for (int i = 0; i < (int)nodes.size(); i++)
        {
            int nextEdge = next[i];

            if (nodes[i].label == dstLabel)
            {
                if (nodes[i].link.size() == 0)
                {
                    printf("Warning: nodes[%d](%d, %d).link.size() == 0\n", i, nodes[i].motionIdx, nodes[i].frameIdx);
                    exit(-1);
                }
                else
                {
                    int ndst0 = edges[nodes[i].link[0]].dst; 
                    if (nodes[ndst0].motionIdx == nodes[i].motionIdx && nodes[ndst0].frameIdx > nodes[i].frameIdx)
                    {
                        // set the next edge to the edge towards the next frame
                        nextEdge = nodes[i].link[0];
                    }
                    else
                    {
                        //printf("%d(%d)\n", nodes[i].motionIdx, nodes[i].frameIdx);
                        nextEdge = nodes[i].link[0];
                        // force to transit to rest pose
                        if (nodes[i].label != 1 &&                                  // walk
                            nodes[i].label != 2)                                    // run
                        //if (false)
                        {
                            for (int j = 0; j < (int)nodes[i].link.size(); j++)
                            {
                                if (edges[nodes[i].link[j]].rest != 0)
                                {
                                    nextEdge = nodes[i].link[j];
                                    break;
                                }
                            }
                        }
                        //printf("%d(%d) --> %d(%d)\n", nodes[edges[nextEdge].src].motionIdx, nodes[edges[nextEdge].src].frameIdx,
                        //                              nodes[edges[nextEdge].dst].motionIdx, nodes[edges[nextEdge].dst].frameIdx);
                    }
                    /*for (int j = 0; j < (int)nodes[i].link.size(); j++)
                    {
                        int dst = edges[nodes[i].link[j]].dst;
                        if (nodes[dst].motionIdx == nodes[i].motionIdx &&
                            nodes[dst].frameIdx == nodes[i].frameIdx + 1)
                        {
                            nextEdge = nodes[i].link[j];
                            break;
                        }
                    }*/
                }
            }

            nodes[i].next.push_back(nextEdge);

            if (nextEdge == -1)
            {
                printf("Warning: node[%d](%d, %d) cannot reach label %d.\n", i, nodes[i].motionIdx, nodes[i].frameIdx, dstLabel);
                //exit(-1);
            }
        }
    }

    printf("done.\n");

    printf("Total edges: %d\n", edges.size());

    ////////////////////////////////////////////////////////////////////////////

    printf("Constructing clips... ");

    // construct edge clips
    for (size_t eid = 0; eid < edges.size(); eid++)
    {
        //printf("edge(%d)  ", eid);

        Motion *clip = NULL;

        Edge &e = edges[eid];
        Node &nsrc = nodes[e.src];
        Node &ndst = nodes[e.dst];

        if (nsrc.motionIdx != ndst.motionIdx || e.length != ndst.frameIdx - nsrc.frameIdx)      // transition between two motions
        {
            //printf("src(%d, %d) dst(%d, %d) %d\n", nsrc.motionIdx, nsrc.frameIdx, ndst.motionIdx, ndst.frameIdx, e.length);
            try
            {
                Transition *tran = new Transition(library->getMotion(nsrc.motionIdx), nsrc.frameIdx, library->getMotion(ndst.motionIdx), ndst.frameIdx, e.theta, e.x0, e.z0);
                clip = tran->getBlendedMotion();
                delete tran;
            }
            catch (std::exception &e)
            {
                printf("%s\n", e.what());
                exit(-1);
            }
        }
        else                                                                                    // forward edge
        {
            //printf("forward src(%d, %d) dst(%d, %d) %d\n", nsrc.motionIdx, nsrc.frameIdx, ndst.motionIdx, ndst.frameIdx, e.length);
            Motion *motion = library->getMotion(nsrc.motionIdx);
            clip = new Motion(e.length + 1, library->getSkeleton());
            if (e.length != ndst.frameIdx - nsrc.frameIdx)
            {
                printf("Error: edges[%d].length != nodes[%d].frameIdx - nodes[%d].frameIdx\n", eid, e.dst, e.src);
            }

            for (int i = 0, j = nsrc.frameIdx; i < e.length + 1; i++, j++)
            {
                clip->SetPosture(i, *motion->GetPosture(j));
            }
        }

        clips.push_back(clip);
    }

    printf("done.\n");
        
    reset();

    printf("Generating motion graph: done.\n");
}
コード例 #3
0
// k := window size
void MotionGraph::genCandidates(std::ofstream &os, int motionIdxA, int motionIdxB, int k)
{
    Skeleton *skeleton = library->getSkeleton();
    Motion *motionA = library->getMotion(motionIdxA);
    Motion *motionB = library->getMotion(motionIdxB);
    if (skeleton == NULL || motionA == NULL || motionB == NULL)
    {
        printf("Error: in genCandidates().\n");
        exit(-1);
    }

    int numFramesA = motionA->GetNumFrames();
    int numFramesB = motionB->GetNumFrames();

    printf("motionIdxA = %d, motionIdxB = %d\n", motionIdxA, motionIdxB);
    printf("numFramesA = %d, numFramesB = %d\n", numFramesA, numFramesB);
    os << "#motionIndex" << std::endl << motionIdxA << ' ' << motionIdxB << std::endl;
    os << "#motionName" << std::endl << library->getName(motionIdxA) << ' ' << library->getName(motionIdxB) << std::endl;
    os << "#numFrames" << std::endl << numFramesA << ' ' << numFramesB << std::endl;

    PointCloud **pcListA = new PointCloud *[numFramesA];
    PointCloud **pcListB = new PointCloud *[numFramesB];

    for (int i = 0; i < numFramesA; i++)
    {
        skeleton->setPosture(*(motionA->GetPosture(i)));
        pcListA[i] = new PointCloud(skeleton);
    }
    for (int i = 0; i < numFramesB; i++)
    {
        skeleton->setPosture(*(motionB->GetPosture(i)));
        pcListB[i] = new PointCloud(skeleton);
    }

    printf("Form distance matrix...\n");

    double *dist = new double[numFramesA * numFramesB]();   // distance of any pair of windows

    int iBegin = 0;
    int iEnd = numFramesA - k;
    int jBegin = k - 1;
    int jEnd = numFramesB - 1;

    printf("Calculating distances...\n");

    for (int i = iBegin; i <= iEnd; i++)             // window of motionA: [i..i+k-1]
    {
        if (i % 10 == 0)
            printf("Calculating (%d, %d)...\n", i, 0);

        for (int j = jBegin; j <= jEnd; j++)         // window of motionB: [j-k+1..j]
        {
            // form point cloud over k frames
            PointCloud pcA(&pcListA[i], k);
            PointCloud pcB(&pcListB[j - k + 1], k);

            int index = i * numFramesB + j;
            dist[index] = distance(&pcA, &pcB);     // distance
        }
    }

    printf("Calculating distances... done.\n");

    //std::vector< std::pair<int, int> > minList;     // local minimum list
    // local minimum list
    std::vector<WindowPair> minList;
    
    // search local minimums
    //bool *mark = new bool[numFramesA * numFramesB]();   // traversed
    for (int i = iBegin; i <= iEnd; i++)
    {
        for (int j = jBegin; j <= jEnd; j++)
        {
            int index = i * numFramesB + j;
            bool isMin = true;
            for (int ii = i - 2; ii <= i + 2; ii++)
            {
                for (int jj = j - 2; jj <= j + 2; jj++)
                {
                    if (ii >= iBegin && ii <= iEnd &&
                        jj >= jBegin && jj <= jEnd &&
                        dist[index] > dist[ii * numFramesB + jj])
                        isMin = false;
                }
            }
            if (isMin)
            {
                WindowPair pair;
                pair.i = i;
                pair.j = j;
                pair.dist = dist[index];
                minList.push_back(pair);
            }
        }
    }

    std::sort(minList.begin(), minList.end());

    printf("Local minimum list:\n");

    int minListSize = 0;
    for (size_t i = 0; i < minList.size(); i++)
    {
        if (!(motionIdxA == motionIdxB && minList[i].i + 39 == minList[i].j))
            minListSize++;
    }

    os << "#minListSize" << std::endl << minListSize << std::endl;
    os << "#i j distance theta x0 z0" << std::endl;

    for (size_t i = 0; i < minList.size(); i++)
    {
        double theta, x0, z0;
        PointCloud pcA(&pcListA[minList[i].i], k);
        PointCloud pcB(&pcListB[minList[i].j - k + 1], k);
        distance(&pcA, &pcB, &theta, &x0, &z0);
        //printf("%4d %4d %8.4lf   %lf %lf %lf\n", minList[i].i, minList[i].j, minList[i].dist, theta, x0, z0);
        if (!(motionIdxA == motionIdxB && minList[i].i + 39 == minList[i].j))
            os << minList[i].i << ' ' << minList[i].j << ' ' << minList[i].dist << ' ' << theta << ' ' << x0 << ' ' << z0 << std::endl;
    }
    
    delete [] dist;

    for (int i = 0; i < numFramesA; i++)
        delete pcListA[i];
    for (int i = 0; i < numFramesB; i++)
        delete pcListB[i];
    delete [] pcListA;
    delete [] pcListB;
    
    printf("genCandidates(): done.\n");
}