下面代码中的想法是让一堆"漫游者"对象慢慢地将图像"绘制"到画布上。问题是,这段代码似乎只适用于正方形图像(在代码中,正方形图像被识别为"隐藏"(因为它是由"画家"揭开的),并且它是从名为"UncoverTest.png"的文件中加载的),而不是矩形图像,这对我来说很神秘。当尝试使用除正方形外的任何东西时,我会得到分割错误。据我所知,当我进入循环迭代Agent类型的向量(在for (vector<Agent>::iterator iter = agents.begin(); iter != agents.end();++iter)
行)时,出现了分割错误。
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace cv;
//#define WINDOW_SIZE 500
#define STEP_SIZE 10.0
#define NUM_AGENTS 100
/********************/
/* Agent class definition and class prototypes */
/********************/
class Agent {
public:
Agent();
int * GetLocation(void);
void Move(void);
void Draw(Mat image);
int * GetSize(void);
private:
double UnifRand(void);
int * location;
int * GetReveal(void);
Mat hidden;
};
int * Agent::GetSize(void) {
int * size = new int[2];
size[0] = hidden.cols;
size[1] = hidden.rows;
return (size);
}
int * Agent::GetReveal(void) {
int * BGR = new int[3];
location = GetLocation();
for (int i = 0; i < 3; i++) {
BGR[i] = hidden.data[hidden.step[0]*location[0] + hidden.step[1]*location[1] + i];
}
return (BGR);
}
void Agent::Draw(Mat image) {
int * location = GetLocation();
int * color = GetReveal();
for (int i = 0;i < 3;i++) {
image.data[image.step[0]*location[0] + image.step[1]*location[1] + i] = color[i];
}
}
void Agent::Move(void) {
int dx = (int)(STEP_SIZE*UnifRand() - STEP_SIZE/2);
int dy = (int)(STEP_SIZE*UnifRand() - STEP_SIZE/2);
location[0] += (((location[0] + dx >= 0) & (location[0] + dx < hidden.cols)) ? dx : 0);
location[1] += (((location[1] + dy >= 0) & (location[1] + dy < hidden.rows)) ? dy : 0);
}
Agent::Agent() {
location = new int[2];
hidden = imread("UncoverTest.png",1);
location[0] = (int)(UnifRand()*hidden.cols);
location[1] = (int)(UnifRand()*hidden.rows);
}
double Agent::UnifRand(void) {
return (rand()/(double(RAND_MAX)));
}
int * Agent::GetLocation(void) {
return (location);
}
/********************/
/* Function prototypes unrelated to the Agent class */
/********************/
void DrawAgents(void);
/********************/
/* Main function */
/********************/
int main(void) {
DrawAgents();
return (0);
}
void DrawAgents(void) {
vector<Agent> agents;
int * size = new int[2];
Mat image;
for (int i = 0; i < NUM_AGENTS; i++) {
Agent * a = new Agent();
agents.push_back(* a);
if (i == 0) {
size = (* a).GetSize();
}
}
// cout << size[0] << " " << size[1] << endl;
image = Mat::zeros(size[0],size[1],CV_8UC3);
cvNamedWindow("Agent Example",CV_WINDOW_AUTOSIZE);
cvMoveWindow("Agent Example",100,100);
for (int stop = 1;stop != 27;stop = cvWaitKey(41)) {
for (vector<Agent>::iterator iter = agents.begin(); iter != agents.end();++iter) {
(* iter).Move();
(* iter).Draw(image);
} imshow("Agent Example",image);
}
}
有谁能向我解释一下这个错误是如何产生的正方形图像,以及如何解决这个问题?
我不完全理解你的代码,但根据你最后的评论,"画布的步进"我想我可以看到你有几个情况,你可能试图访问超出范围的数据在你的"隐藏"垫和"图像"垫。
恐怕我只能提供建议
void Agent::Draw(Mat image) {
int * location = GetLocation();
int * color = GetReveal();
for (int i = 0;i < 3;i++) {
image.data[image.step[0]*location[0] + image.step[1]*location[1] + i] = color[i];
}
}
这里你访问GetLocation,它在Agent构建过程中从一个随机数字乘以隐藏垫的大小实例化。我担心这里你会得到一个"索引越界"类型的错误,当访问图像。数据矩阵。所以这可能是首先要检查的。
int * Agent::GetReveal(void) {
int * BGR = new int[3];
location = GetLocation();
for (int i = 0; i < 3; i++) {
BGR[i] = hidden.data[hidden.step[0]*location[0] + hidden.step[1]*location[1] + i];
}
return (BGR);
}
您使用getLocation(),它将返回一个远远大于隐藏图像大小的点。我很确定这里也会出现错误。位置应该从hidden.cols()和hidden.rows()派生。
只看了一眼,但我肯定会在getLocation()返回的值周围进行一些检查,如果这样的值可以从mat矩阵访问。
此外,虽然我不完全确定,因为我认为你在两种不同的方式使用位置,但如果位置是你的Draw(图像)中的某个点,那么你需要调整以下内容:
location[0] += (((location[0] + dx >= 0) & (location[0] + dx < hidden.cols)) ? dx : 0);
location[1] += (((location[1] + dy >= 0) & (location[1] + dy < hidden.rows)) ? dy : 0);
并考虑到隐藏图像的宽度,比如
location[0] += (((location[0] + dx >= 0) & (location[0] + dx + hidden.cols < maxWidth)) ? dx : 0);
location[1] += (((location[1] + dy >= 0) & (location[1] + dy + hidden.rows < maxHeight)) ? dy : 0);
其中maxWidth和maxHeight是图像的宽度。
希望这能让你走上正轨。
如果您在Linux环境中,您可以使用valgrind来准确地找出分段错误发生的位置。只需在程序名称或执行程序的方式之前键入valgrind即可。例如,如果您使用以下命令执行程序:
你好安全性
发出以下命令: