【问题标题】:Opencv Rect only creating one rectangleOpencv Rect 只创建一个矩形
【发布时间】:2014-06-17 07:14:49
【问题描述】:

在我尝试实现粒子过滤器时,我首先在图像中的汽车周围手动绘制了一个矩形(x,y,w,h)(红色),然后我选取了 50 个粒子,并为它们分配了噪声,即x=x+noise(0,15) 和 y=y+noise(0,15)。

然后我想用绿色为每个粒子绘制所有矩形,但不是显示 50 个矩形,而是只显示一个矩形。

#include<opencv2\core\core.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\highgui\highgui.hpp>

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

using namespace cv;
using namespace std;



const int N = 50;// no of particles

string intToString(int number){

    //this function has a number input and string output
    std::stringstream ss;
    ss << number;
    return ss.str();
}



int main()
{


    Mat frame;
    frame = imread("f (1).png");
    namedWindow("Out");


    //locating the car manually
    Rect car(175, 210, 42, 31);


    //making a rectangle around the car
    rectangle(frame, car, Scalar(0, 0,255), 1, 8, 0);



    //getting tht height and width of the frame
    const int FRAME_HEIGHT = frame.rows;
    const int FRAME_WIDTH = frame.cols;


    //Particle filter initialization

    Mat Init = (Mat_<float>(4, 1) << car.x, car.y, 0, 0);


    //for a gaussian noise distribution
    std::default_random_engine generator;
    std::normal_distribution<double> distribution(0, 15);


    //Initializing the particles
    std::vector<cv::Mat> particle(N, cv::Mat(4, 1, CV_32F));


    cout << car.x << " " << car.y << "\n";

    for (int i = 0; i < N; i++)
    {
        particle[i].at<float>(0, 0) = Init.at<float>(0, 0) + distribution(generator);
        particle[i].at<float>(1, 0) = Init.at<float>(1, 0) + distribution(generator);
        particle[i].at<float>(2, 0) = 0.0;
        particle[i].at<float>(3, 0) = 0.0;
        cout << particle[i] << "\n";
    }

    for (int i = 0; i < N; i++)
    {
        int x = particle[i].at<float>(0, 0);
        int y = particle[i].at<float>(1, 0);

        rectangle(frame, Rect(x, y, 42, 31), Scalar(0, 255, 0), 1, 8, 0);
    }

    imshow("Out", frame);


    waitKey();





    return 0;
}

输出如下所示

粒子xy坐标如下图,第一项是手动硬编码的汽车,其余都是粒子坐标。

【问题讨论】:

  • 在绘制之前,棱角的位置是什么?似乎所有粒子的位置几乎相同......
  • 好吧,将您的问题分成多个任务并评估每个任务,首先:您的随机数生成器distribution(generator) 是否正常工作?例如。将其替换为rand()%15
  • @marol 的出色回答。尝试更简单的容器,例如 std::vector<:rect> 或 std::vector<:point>.
  • 可以通过在绘图前再次打印粒子位置来简化定位问题。
  • @Micka 这正是我在回答中所建议的。

标签: c++ opencv particle-filter


【解决方案1】:

不幸的是,问题可能出在向量初始化中。行内:

 //Initializing the particles
    std::vector<cv::Mat> particle(N, cv::Mat(4, 1, CV_32F));

您要做的是创建 N 个 Mat 对象,这些对象已初始化为 float 类型的 4 x 1 大小。所以这似乎没问题......等等! 如果向量中的所有 Mat 对象共享相同的矩阵数据怎么办?我们都知道 Mat 容器有一个 header 和数据。当标头相互分配或执行复制构造函数时,不会复制数据。就像我们的情况一样。究竟是什么让我们想象一下向量构造函数是如何工作的:

template<class T>
vector::vector (size_type n, const value_type& val = value_type(),
                 const allocator_type& alloc = allocator_type()) {
    // how it can be written? Probably in the following way:
    this->resize(n); // allocates using allocator
    for(int i=0;i<n;i++)
         this->innerBuffer[i] = alloc(val); // runs copy constructor with argument val
                    // in our case, this is cv::Mat(const cv::Mat &)
}

如果您考虑复制 cv::Mat 容器,只会复制标头。如果您想克隆数据本身,则必须直接指定它,例如使用 Mat::clone() 方法。而且向量构造函数绝对不使用clone()。所以数据没有被克隆,所有的 Mat 对象共享相同的数据,尽管 headers 不同!

您可以轻松检查这是否属实(如果不是,我会感到惊讶):更改代码片段:

 for (int i = 0; i < N; i++)
    {
        particle[i].at<float>(0, 0) = Init.at<float>(0, 0) + distribution(generator);
        particle[i].at<float>(1, 0) = Init.at<float>(1, 0) + distribution(generator);
        particle[i].at<float>(2, 0) = 0.0;
        particle[i].at<float>(3, 0) = 0.0;
        cout << particle[i] << "\n"; // it is obvius that HERE particles are different
                 // beacuse in the next loop run you overwrite them!
    }

    for (int i = 0; i < N; i++)
    {
        int x = particle[i].at<float>(0, 0);
        int y = particle[i].at<float>(1, 0);

        rectangle(frame, Rect(x, y, 42, 31), Scalar(0, 255, 0), 1, 8, 0);
    }

 for (int i = 0; i < N; i++)
    {
        particle[i].at<float>(0, 0) = Init.at<float>(0, 0) + distribution(generator);
        particle[i].at<float>(1, 0) = Init.at<float>(1, 0) + distribution(generator);
        particle[i].at<float>(2, 0) = 0.0;
        particle[i].at<float>(3, 0) = 0.0;

    }

    for (int i = 0; i < N; i++)
    {
        cout << particle[i] << "\n";

        int x = particle[i].at<float>(0, 0);
        int y = particle[i].at<float>(1, 0);

        rectangle(frame, Rect(x, y, 42, 31), Scalar(0, 255, 0), 1, 8, 0);
    }

我希望所有的粒子都是一样的。

参考: (here)

 vector(size_type __n, const value_type& __value,
00199          const allocator_type& __a = allocator_type())
00200       : _Base(__n, __a)
00201       { this->_M_impl._M_finish = std::uninitialized_fill_n(this->
00202                                 _M_impl._M_start,
00203                                 __n, __value); }
00204 

【讨论】:

    猜你喜欢
    • 2015-07-12
    • 2016-04-24
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 2011-12-07
    • 2022-01-22
    • 2016-04-26
    • 1970-01-01
    相关资源
    最近更新 更多