4

OpenCVを使用したハフライン検出を示す短いプログラムを作成しました。

最後のステップでは、コードは元のぼやけたグレースケール画像を取得し、キャニーエッジの検出結果をオーバーレイしてから、ハフ変換で検出された線をオーバーレイします。

ハフラインは赤一色(R = 255)、3pxのラインとしてレンダリングされていますが、それらをオーバーレイすると、何らかの理由で下の画像が透けて見えます。以下の例。

元の画像:元の画像

キャニーエッジ+ハフラインがオーバーレイされたぼやけたグレースケール画像:ここに画像の説明を入力してください

拡大セグメント:ここに画像の説明を入力してください

ご覧のとおり、グレースケール画像は(明らかに)赤一色になっています。どうしてこれなの?

完全なコードは以下のとおりです。

houghtest.cpp

#include <stdlib.h>
#include <iostream>
#include <stdio.h>

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include "toolbarconfig.h"


using namespace cv;


// Global variables
const char* window_name = "Hough Line Detection";

ToolbarConfig
    gaussian = ToolbarConfig(0, 15, 1, 6),
    canny = ToolbarConfig(20, 150, 2, 40),
    hough = ToolbarConfig(50, 400, 10, 200);

Mat input;

// Function prototypes
void update(int, void*);
void chromakey(const Mat under, const Mat over, Mat *dst, const Scalar& color);
void help();


/**
 * Creates an interactive example of running hough line detection on a
 * sample image
 */
int main( int argc, char** argv ) {
    const char* filename = argc >= 2 ? argv[1] : "pic1.png";

    input = imread(filename, CV_LOAD_IMAGE_COLOR); if(input.empty()) {
        help();

        std::cout << "Can not open " << filename << std::endl;
        return -1;
    }

    // Convert the image to grayscale
    cvtColor(input, input, CV_BGR2GRAY);

    // Create a window
    namedWindow(window_name, CV_WINDOW_AUTOSIZE);

    // Create trackbars for the user to enter thresholds
    createTrackbar("Gaussian Kernel Size", window_name, &(gaussian.t_current), gaussian.tmax(), update);
    createTrackbar("Canny Min Threshold", window_name, &(canny.t_current), canny.tmax(), update);
    createTrackbar("Hough Line Threshold", window_name, &(hough.t_current), hough.tmax(), update);

    // Show the image
    update(NULL, NULL);

    // Wait until user exit program by pressing a key
    waitKey(0);

    return 0;
}


/**
 * Trackbar callback - updates the display
 */
void update(int, void*) {
    const int CANNY_RATIO = 3, CANNY_KERNEL_SIZE = 3;

    Mat blurred_input, canny_edges, hough_lines;

    // Reduce noise with a gaussian kernel
    if(gaussian.current() != 0) {
        blur(input, blurred_input, Size(gaussian.current(), gaussian.current()));
    } else {
        blurred_input = input;
    }

    // Run Canny edge detector
    Canny(blurred_input, canny_edges, canny.current(), canny.current()*CANNY_RATIO, CANNY_KERNEL_SIZE);

    // ==== Begin Hough line detector phase

    // Create a vector to store the located lines in
    vector<Vec2f> line_vector;

    // Run the transform
    HoughLines(canny_edges, line_vector, 1, CV_PI/180, hough.current(), 0, 0);

    //std::cout << lines.size() << " lines detected" << std::endl;

    // Prepare the hough_lines image
    hough_lines = Mat::zeros(canny_edges.rows, canny_edges.cols, CV_8UC3);

    // Draw detected lines into an image
    for(size_t i = 0; i < line_vector.size(); i++) {
        float rho = line_vector[i][0], theta = line_vector[i][1];
        Point pt1, pt2;

        double a = cos(theta), b = sin(theta);
        double x0 = a*rho, y0 = b*rho;

        pt1.x = cvRound(x0 + 1000*(-b));
        pt1.y = cvRound(y0 + 1000*(a));
        pt2.x = cvRound(x0 - 1000*(-b));
        pt2.y = cvRound(y0 - 1000*(a));

        line(hough_lines, pt1, pt2, Scalar(0, 0, 255), 3, 0);
    }

    // Overlay the hough lines onto the original blurred image
    Mat blurred_input_color, canny_edges_color, input_with_canny, combined_images;
    cvtColor(blurred_input, blurred_input_color, CV_GRAY2BGR);
    cvtColor(canny_edges, canny_edges_color, CV_GRAY2BGR);

    chromakey(blurred_input_color, canny_edges_color, &input_with_canny, Scalar(0, 0, 0));
    chromakey(input_with_canny, hough_lines, &combined_images, Scalar(0, 0, 0));

    // Display the result
    imshow(window_name, combined_images);
}

/**
 * Takes two images and overlays them, using color as a chroma-key
 * Any pixels in the 'over' image that match the given color value will
 * effectively be transparent - the 'under' image will show through
 *
 * @precondition: All passed images must first be in BGR format
 */
void chromakey(const Mat under, const Mat over, Mat *dst, const Scalar& color) {
    // Mats must be the same size
    if(under.rows != over.rows || under.cols != over.cols) {
        std::cout << "Error, image dimensions must match" << std::endl;
        return;
    }

    // Create the destination matrix
    *dst = Mat::zeros(under.rows, under.cols, CV_8UC3);

    for(int y=0; y<under.rows; y++) {
        for(int x=0; x<under.cols; x++) {
            dst->at<Vec3b>(y,x)[0] = over.at<Vec3b>(y,x)[0] == color[0] ? under.at<Vec3b>(y,x)[0] : over.at<Vec3b>(y,x)[0];
            dst->at<Vec3b>(y,x)[1] = over.at<Vec3b>(y,x)[1] == color[1] ? under.at<Vec3b>(y,x)[1] : over.at<Vec3b>(y,x)[1];
            dst->at<Vec3b>(y,x)[2] = over.at<Vec3b>(y,x)[2] == color[2] ? under.at<Vec3b>(y,x)[2] : over.at<Vec3b>(y,x)[2];
        }
    }
}


/**
 * Prints usage information
 */
void help() {
    std::cout << "\nThis program demonstrates line finding with the Hough transform.\n" "Usage:\n"
    "./houghlines <image_name>, Default is pic1.png\n" << std::endl;
}

routerconfig.h

#ifndef TOOLBARCONFIG_H
#define TOOLBARCONFIG_H

class ToolbarConfig {
    public:
    ToolbarConfig(int min, int max, int stepsize, int current);

    int w2t(int world_value);
    int t2w(int toolbar_value);

    int current();
    int tmax();
    int tmin();

    int min;
    int max;
    int stepsize;

    int t_current;
};

#endif

routerconfig.cpp

#include <algorithm>

#include "toolbarconfig.h"

ToolbarConfig::ToolbarConfig(int min, int max, int stepsize, int current) {
    this->min = min;
    this->max = max;
    this->stepsize = stepsize;
    this->t_current = this->w2t(current);
}

int ToolbarConfig::w2t(int world_value) {
    return int((std::min(std::max(world_value, min), max) - min) / stepsize);
}

int ToolbarConfig::t2w(int toolbar_value) {
    return toolbar_value * stepsize + min;
}

int ToolbarConfig::current() {
    return t2w(t_current);
}

int ToolbarConfig::tmax() {
    return w2t(max);
}

int ToolbarConfig::tmin() {
    return w2t(min);
}

必要に応じて、Makefileも提供してください。

前もって感謝します。

4

1 に答える 1

7

エラーは次の場所にある必要があります。

dst->at<Vec3b>(y,x)[0] = over.at<Vec3b>(y,x)[0] == color[0] ? under.at<Vec3b>(y,x)[0] : over.at<Vec3b>(y,x)[0];
dst->at<Vec3b>(y,x)[1] = over.at<Vec3b>(y,x)[1] == color[1] ? under.at<Vec3b>(y,x)[1] : over.at<Vec3b>(y,x)[1];
dst->at<Vec3b>(y,x)[2] = over.at<Vec3b>(y,x)[2] == color[2] ? under.at<Vec3b>(y,x)[2] : over.at<Vec3b>(y,x)[2];

初めて電話するとき

chromakey(blurred_input_color, canny_edges_color, &input_with_canny, Scalar(0, 0, 0));

canny_edges_color白いピクセル値は (255, 255, 255) であるため、上記の比較ではover各チャネルの値を取得するため、ピクセルの色は (255, 255, 255) になり、画像は正しく表示されます。

ただし、2 番目のケースでは:

chromakey(input_with_canny, hough_lines, &combined_images, Scalar(0, 0, 0));

赤のピクセルのhugh_lines値は (0, 0, 255) であるため、最初の 2 つの比較では の値が取得されますunder

over.at<Vec3b>(y,x)[0] == color[0]

over.at<Vec3b>(y,x)[1] == color[1].

dst->at<Vec3b>(y,x)[2]255 値のみが取得されます。線が実線で表示されるようにするには、この場合ではなくdst->at<Vec3b>(y,x)[0] = 0and にする必要があります。dst->at<Vec3b>(y,x)[1] = 0


また、この回答によれば、おそらく *dst を次のように初期化する必要があります。

*dst = Mat(under.rows,under.cols,CV_8UC3,CV_RGB(0,0,0));

3チャンネルマットなので。

于 2012-09-17T17:14:17.727 に答える