Beispiel #1
0
TriMeshf box(const bbox3f &bbox, const vec4f& color)
{
    auto extent = bbox.getExtent();
    auto center = bbox.getCenter();
    TriMeshf result = box(extent.x, extent.y, extent.z, color);
    for (auto &v : result.getVertices())
    {
        v.position += center;
    }
    return result;
}
vector<UINT> SegmentorFelzenswalb::segment(const TriMeshf& mesh) const
{
    size_t N = mesh.getVertices().size();
    cout << "Segmenting mesh with " << N << " vertices...";
    
    const MeshEdges& es = getEdges(mesh);
    size_t Ne = es.size();
    edge* edges = new edge[Ne];
    const auto& verts = mesh.getVertices();

    for (size_t i = 0; i < Ne; i++)
    {
        int a = es[i].first;
        int b = es[i].second;

        edges[i].a = a;
        edges[i].b = b;

        const vec3f& n1 = verts[a].normal;
        const vec3f& n2 = verts[b].normal;
        const vec3f& p1 = verts[a].position;
        const vec3f& p2 = verts[b].position;

        float dx = p2.x - p1.x;
        float dy = p2.y - p1.y;
        float dz = p2.z - p1.z;
        float dd = sqrt(dx * dx + dy * dy + dz * dz);
        dx /= dd; dy /= dd; dz /= dd;

        float dot = vec3f::dot(n1, n2);
        float dot2 = n2.x * dx + n2.y * dy + n2.z * dz;
        float ww = 1.0f - dot;
        if (dot2 > 0) { ww = ww * ww; } // make it much less of a problem if convex regions have normal difference
        if (colorWeight > 0.0f)
        {
            const vec4f& c1 = verts[a].color;
            const vec4f& c2 = verts[b].color;
            //const float d = vec3f::dist(c1, c2);
            //ww = (1 - m_colorWeight) * ww +  m_colorWeight * d;
            const vec4f& c1hsl = ml::ColorUtils::rgbToHsl<vec4f>(c1);
            const vec4f& c2hsl = ml::ColorUtils::rgbToHsl<vec4f>(c2);
            //const vec4f& c1rgb = ml::ColorUtils::hslToRgb<vec4f>(c1hsl);
            //const vec4f& c2rgb = ml::ColorUtils::hslToRgb<vec4f>(c2hsl);
            // Find difference in H and L, handling wrapping and make range [0,1]
            const float hdiff = 2.0f * std::min(fabsf(c1hsl[0] - c2hsl[0]), fabsf(c2hsl[0] - c1hsl[0] + 1));
            const float ldiff = 2.0f * std::min(fabsf(c1hsl[2] - c2hsl[2]), fabsf(c2hsl[2] - c1hsl[2] + 1));
            const float hldiff = sqrtf(hdiff*hdiff + ldiff*ldiff);
            ww = (1.0f - colorWeight) * ww + colorWeight * hldiff;
        }

        edges[i].w = ww;
    }
    cout << "graph done... ";

    // Segment!
    universe* u = segment_graph(static_cast<int>(N), static_cast<int>(Ne), edges, threshold);
    cout << u->num_sets() << " initial segs. ";

    // Join small segments
    for (int j = 0; j < Ne; j++)
    {
        int a = u->find(edges[j].a);
        int b = u->find(edges[j].b);
        if ((a != b) && ((u->size(a) < minSegmentVertices) || (u->size(b) < minSegmentVertices))) {
            u->join(a, b);
        }
    }

    cout << " Done: " << u->num_sets() << " final segs" << endl;
    // Return segment indices
    vector<UINT> out(N);
    for (int q = 0; q < N; q++)
    {
        out[q] = u->find(q);
    }
    delete u;
    return out;
}