// Add multiple variables
void drwnFrankCopula::setVariables(const drwnClique& c)
{
	// Must have size 2, 3, or 4 (for now)
	DRWN_ASSERT_MSG(c.size() >= 2 && c.size() <= 4, "Archimedian copula must have size between 2 and 4")

	// Call set variables from parent
	drwnCdf::setVariables(c);
	
	// Calculate number of subsets of variables
	_numSubsets = 1 << size();
	_partialDerivs = new range_type[_numSubsets << 1];
}
Beispiel #2
0
void drwnLBPFilterBank::filter(const cv::Mat& img, std::vector<cv::Mat>& response) const
{
    // check input
    DRWN_ASSERT(img.data != NULL);
    if (response.empty()) {
        response.resize(this->numFilters());
    }
    DRWN_ASSERT(response.size() == this->numFilters());

    if (img.channels() != 1) {
        cv::Mat tmp(img.rows, img.cols, img.depth());
        cv::cvtColor(img, tmp, CV_RGB2GRAY);
        return filter(tmp, response);
    }
    DRWN_ASSERT_MSG(img.depth() == CV_8U, "image must be 8-bit");

    // allocate output channels as 32-bit floating point
    for (unsigned i = 0; i < response.size(); i++) {
        if ((response[i].rows == img.rows) && (response[i].cols == img.cols) &&
            (response[i].depth() == CV_32F) && (response[i].channels() == 1)) {
            response[i].setTo(0.0f);
        } else {
            response[i] = cv::Mat::zeros(img.rows, img.cols, CV_32FC1);
        }
    }

    for (int y = 0; y < img.rows; y++) {

        const unsigned char *p = img.ptr<const unsigned char>(y);
        const unsigned char *p_prev = (y == 0) ? p : img.ptr<const unsigned char>(y - 1);
        const unsigned char *p_next = (y == img.rows - 1) ? p : img.ptr<const unsigned char>(y + 1);

        // 4-connected neighbourhood
        for (int x = 0; x < img.cols; x++) {
            if (p[x] > p_prev[x]) response[0].at<float>(y, x) = 1.0f;
            if ((x < img.cols - 1) && (p[x] > p[x + 1])) response[1].at<float>(y, x) = 1.0f;
            if (p[x] > p_next[x]) response[2].at<float>(y, x) = 1.0f;
            if ((x > 0) && (p[x] > p[x - 1])) response[3].at<float>(y, x) = 1.0f;
        }

        // 8-connected neighbourhood
        if (_b8Neighbourhood) {
            for (int x = 0; x < img.cols; x++) {
                if ((p[x] > p_prev[x]) && (x < img.cols - 1) && (p[x] > p[x + 1])) response[4].at<float>(y, x) = 1.0f;
                if ((x < img.cols - 1) && (p[x] > p[x + 1]) && (p[x] > p_next[x])) response[5].at<float>(y, x) = 1.0f;
                if ((p[x] > p_next[x]) && (x > 0) && (p[x] > p[x - 1])) response[6].at<float>(y, x) = 1.0f;
                if ((x > 0) && (p[x] > p[x - 1]) && (p[x] > p_prev[x])) response[7].at<float>(y, x) = 1.0f;
            }
        }
    }
}
void drwnTextonFilterBank::filter(const cv::Mat& img, std::vector<cv::Mat>& response) const
{
    // check input
    DRWN_ASSERT(img.data != NULL);
    if (response.empty()) {
        response.resize(NUM_FILTERS);
    }
    DRWN_ASSERT((int)response.size() == NUM_FILTERS);
    DRWN_ASSERT((img.channels() == 3) && (img.depth() == CV_8U));
    for (int i = 0; i < NUM_FILTERS; i++) {
        if ((response[i].rows != img.rows) || (response[i].cols != img.cols)) {
            response[i] = cv::Mat(img.rows, img.cols, CV_32FC1);
	}
        DRWN_ASSERT((response[i].channels() == 1) && (response[i].depth() == CV_32F));
    }

    int k = 0;

    // color convert
    DRWN_LOG_DEBUG("Color converting image...");
    cv::Mat imgCIELab8U(img.rows, img.cols, CV_8UC3);
    cv::cvtColor(img, imgCIELab8U, CV_BGR2Lab);
    cv::Mat imgCIELab(img.rows, img.cols, CV_32FC3);
    imgCIELab8U.convertTo(imgCIELab, CV_32F, 1.0 / 255.0);

    cv::Mat greyImg(img.rows, img.cols, CV_32FC1);
    const int from_to[] = {0, 0};
    cv::mixChannels(&imgCIELab, 1, &greyImg, 1, from_to, 1);

    // gaussian filter on all color channels
    DRWN_LOG_DEBUG("Generating gaussian filter responses...");
    cv::Mat gImg32f(img.rows, img.cols, CV_32FC3);
    for (double sigma = 1.0; sigma <= 4.0; sigma *= 2.0) {
        const int h = 2 * (int)(_kappa * sigma) + 1;
        cv::GaussianBlur(imgCIELab, gImg32f, cv::Size(h, h), 0);
        cv::split(gImg32f, &response[k]);
        k += 3;
    }

    // derivatives of gaussians on just greyscale image
    DRWN_LOG_DEBUG("Generating derivative of gaussian filter responses...");
    for (double sigma = 2.0; sigma <= 4.0; sigma *= 2.0) {
        // x-direction
        cv::Sobel(greyImg, response[k++], CV_32F, 1, 0, 1);
        cv::GaussianBlur(response[k - 1], response[k - 1],
            cv::Size(2 * (int)(_kappa * sigma) + 1, 2 * (int)(3.0 * _kappa * sigma) + 1), 0);

        // y-direction
        cv::Sobel(greyImg, response[k++], CV_32F, 0, 1, 1);
        cv::GaussianBlur(response[k - 1], response[k - 1],
            cv::Size(2 * (int)(3.0 * _kappa * sigma) + 1, 2 * (int)(_kappa * sigma) + 1), 0);
    }

    // laplacian of gaussian on just greyscale image
    DRWN_LOG_DEBUG("Generating laplacian of gaussian filter responses...");
    cv::Mat tmpImg(img.rows, img.cols, CV_32FC1);
    for (double sigma = 1.0; sigma <= 8.0; sigma *= 2.0) {
        const int h = 2 * (int)(_kappa * sigma) + 1;
        cv::GaussianBlur(greyImg, tmpImg, cv::Size(h, h), 0);
        cv::Laplacian(tmpImg, response[k++], CV_32F, 3);
    }

    DRWN_ASSERT_MSG(k == NUM_FILTERS, k << " != " << NUM_FILTERS);
}
Beispiel #4
0
double drwnAlphaExpansionInference::inference(drwnFullAssignment& mapAssignment)
{
    // check factor graph is pairwise
    for (int i = 0; i < _graph.numFactors(); i++) {
        DRWN_ASSERT(_graph[i]->size() <= 2);
    }

    // initialize MAP assignment
    const drwnVarUniversePtr pUniverse(_graph.getUniverse());
    const int nVariables = pUniverse->numVariables();
    mapAssignment.resize(nVariables, 0);
    double bestEnergy = _graph.getEnergy(mapAssignment);
    const int maxAlpha = pUniverse->maxCardinality();
    if (maxAlpha == 1) return bestEnergy;

    drwnFullAssignment assignment(mapAssignment);

    drwnMaxFlow *g = new drwnBKMaxFlow(nVariables);
    g->addNodes(nVariables);

    // iterate until convergence
    bool bChanged = true;
    int lastChanged = -1;
    int nonSubmodularMoves = 0;
    for (int nCycle = 0; bChanged; nCycle += 1) {
        bChanged = false;
        for (int alpha = 0; alpha < maxAlpha; alpha++) {
            if (alpha == lastChanged)
                break;

            // construct graph
            bool bNonSubmodularMove = false;
            g->reset();
            for (int i = 0; i < _graph.numFactors(); i++) {
                const drwnTableFactor *phi = _graph[i];
                if (phi->size() == 1) {
                    // unary
                    const int u = phi->varId(0);
                    const double A = (*phi)[mapAssignment[u]];
                    const double B = (*phi)[alpha % pUniverse->varCardinality(u)];
                    g->addSourceEdge(u, A);
                    g->addTargetEdge(u, B);
                } else if (phi->size() == 2) {
                    // pairwise
                    const int u = phi->varId(0);
                    const int v = phi->varId(1);

                    const int uAlpha = alpha % pUniverse->varCardinality(u);
                    const int vAlpha = alpha % pUniverse->varCardinality(v);

                    if ((uAlpha == mapAssignment[u]) && (vAlpha == mapAssignment[v]))
                        continue;

                    double A = (*phi)[phi->indexOf(v, mapAssignment[v], phi->indexOf(u, mapAssignment[u]))];
                    double B = (*phi)[phi->indexOf(v, vAlpha, phi->indexOf(u, mapAssignment[u]))];
                    double C = (*phi)[phi->indexOf(v, mapAssignment[v], phi->indexOf(u, uAlpha))];
                    double D = (*phi)[phi->indexOf(v, vAlpha, phi->indexOf(u, uAlpha))];

                    if (uAlpha == mapAssignment[u]) {
                        g->addSourceEdge(v, A);
                        g->addTargetEdge(v, B);
                    } else if (vAlpha == mapAssignment[v]) {
                        g->addSourceEdge(u, A);
                        g->addTargetEdge(u, C);
                    } else {
                        // check for submodularity
                        if (A + D > C + B) {
                            // truncate non-submodular functions
                            bNonSubmodularMove = true;
                            const double delta = A + D - C - B;
                            A -= delta / 3 - DRWN_EPSILON;
                            C += delta / 3 + DRWN_EPSILON;
                            B = A + D - C + DRWN_EPSILON;
                        }

                        g->addSourceEdge(u, A);
                        g->addTargetEdge(u, D);

                        B -= A; C -= D; B += DRWN_EPSILON; C += DRWN_EPSILON;
                        DRWN_ASSERT_MSG(B + C >= 0, "B = " << B << ", C = " << C);
                        if (B < 0) {
                            g->addTargetEdge(v, B);
                            g->addTargetEdge(u, -B);
                            g->addEdge(v, u, 0.0, B + C);
                        } else if (C < 0) {
                            g->addTargetEdge(v, -C);
                            g->addTargetEdge(u, C);
                            g->addEdge(v, u, B + C, 0.0);
                        } else {
                            g->addEdge(v, u, B, C);
                        }
                    }
                }
            }

            // run inference
            if (bNonSubmodularMove) {
                nonSubmodularMoves += 1;
            }

            g->solve();
            for (int i = 0; i < nVariables; i++) {
                assignment[i] = (g->inSetS(i) ? alpha % pUniverse->varCardinality(i) : mapAssignment[i]);
            }
            double e = _graph.getEnergy(assignment);

            DRWN_LOG_DEBUG("...cycle " << nCycle << ", iteration " << alpha << " has energy " << e);
            if (e < bestEnergy) {
                bestEnergy = e;
                mapAssignment = assignment;
                lastChanged = alpha;
                bChanged = true;
            }
        }
    }

    // free graph
    delete g;

    DRWN_LOG_DEBUG("..." << nonSubmodularMoves << " non-submodular moves");
    return bestEnergy;
}