草庐IT

c++ - OpenCV 不需要的颜色混合

coder 2024-02-17 原文

我编写了一个简短的程序来演示使用 OpenCV 进行霍夫线检测。

在最后一步,代码采用原始的模糊灰度图像,叠加 Canny 边缘检测结果,然后叠加霍夫变换检测到的线。

hough 线被渲染为纯红色 (R=255),3px 线,但是当我覆盖它们时,由于某种原因下图显示出来。示例如下。

原始图片:

带有 Canny 边缘 + 霍夫线覆盖的模糊灰度图像:

放大片段:

可以看出,灰度图像穿过(明显)纯红色。这是为什么?

完整代码如下:

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;
}

工具栏配置.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

工具栏配置.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。

提前致谢。

最佳答案

错误一定是在这里:

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每个 channel 的值,因此像素的颜色将为 (255, 255, 255),图像将正确显示。

然而,在第二种情况下:

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

你的hugh_lines红色像素的值为 (0, 0, 255),因此对于前两次比较,它们将获得值 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] = 0dst->at<Vec3b>(y,x)[1] = 0而不是在这种情况下。


此外,根据 this answer你应该像这样初始化 *dst:

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

因为它是一个 3 channel 垫。

关于c++ - OpenCV 不需要的颜色混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12454134/

有关c++ - OpenCV 不需要的颜色混合的更多相关文章

  1. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  2. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - rspec 需要 .rspec 文件中的 spec_helper - 2

    我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只

  5. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  6. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  7. ruby 诅咒颜色 - 2

    如何使用Ruby的默认Curses库获取颜色?所以像这样:puts"\e[0m\e[30;47mtest\e[0m"效果很好。在浅灰色背景上呈现漂亮的黑色。但是这个:#!/usr/bin/envrubyrequire'curses'Curses.noecho#donotshowtypedkeysCurses.init_screenCurses.stdscr.keypad(true)#enablearrowkeys(forpageup/down)Curses.stdscr.nodelay=1Curses.clearCurses.setpos(0,0)Curses.addstr"Hello

  8. ruby - Rails 3 的 RGB 颜色选择器 - 2

    状态:我正在构建一个应用程序,其中需要一个可供用户选择颜色的字段,该字段将包含RGB颜色代码字符串。我已经测试了一个看起来很漂亮但效果不佳的。它是“挑剔的颜色”,并托管在此存储库中:https://github.com/Astorsoft/picky-color.在这里我打开一个关于它的一些问题的问题。问题:请建议我在Rails3应用程序中使用一些颜色选择器。 最佳答案 也许页面上的列表jQueryUIDevelopment:ColorPicker为您提供开箱即用的产品。原因是jQuery现在包含在Rails3应用程序中,因此使用基

  9. ruby - 为什么在 ruby​​ 中创建 Rational 不需要新方法 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Rubysyntaxquestion:Rational(a,b)andRational.new!(a,b)我正在阅读ruby镐书,我对创建有理数的语法感到困惑。Rational(3,4)*Rational(1,2)产生=>3/8为什么Rational不需要new方法(我还注意到例如我可以在没有new方法的情况下创建字符串)?

  10. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

随机推荐