C++ 分段错误 OpenCV

Posted

技术标签:

【中文标题】C++ 分段错误 OpenCV【英文标题】:C++ Segmentation Fault OpenCV 【发布时间】:2012-12-30 22:23:21 【问题描述】:

以下代码中的想法是让一堆“流浪者”对象慢慢地将图像“绘制”到画布上。问题是,这段代码似乎只适用于方形图像(在代码中,方形图像被标识为“隐藏”(因为它是由“画家”揭开的)并且它是从名为“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);
  

谁能向我解释一下这个错误是如何只出现在方形图像上的,以及如何解决这个问题?

【问题讨论】:

您需要确定 segvfault 发生的位置。我猜与vector::iterator iter line.有关 是的,这正是我推测的。事实上,在仔细放置了一些打印语句之后,我很确定这就是发生故障的地方。问题是:我该如何处理这些信息? 验证 Move() 和 Draw() 方法是否适用于存在的对象。 所以我在调用draw方法后添加了一条打印语句。我认为如果其中任何一个方法被破坏或无法执行,那么 print 语句将永远不会出现。重新编译可执行文件后,程序成功打印,然后抛出分段错误。因此,换句话说,在迭代器循环完成后它似乎失败了。所以我决定看看 imshow 之后的打印语句是否有效,但它们没有。所以问题似乎出在 imshow 或我传递给它的 Mat 上。建议? 实际上,我必须收回。在 for 循环之外但在 imshow 之前打印语句也不打印。 【参考方案1】:

我不完全理解您的代码,但根据您的最后一条评论,“踩到画布”我想我可以看到您有几种情况,您可能会尝试访问超出范围的数据“隐藏”垫和“图像”垫。

恐怕我只能提供建议

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 已在构建代理期间从一个随机数乘以隐藏垫的大小进行实例化。我担心在访问 image.data 矩阵时会出现“索引越界”类型错误。所以这可能是首先要检查的内容。

就像在

中一样明智
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() 返回的值,以及是否可以从矩阵矩阵访问这样的值。

此外,虽然我不完全确定,因为我认为您以两种不同的方式使用位置,但如果位置是 Draw(image) 中某处的一个点,那么您需要调整以下内容:

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 是图像的宽度。

希望这能让你走上正轨。

【讨论】:

仍在努力更好地了解您的目标,如果以上内容不完全正确,请见谅。【参考方案2】:

如果您在 Linux 环境中,您可以使用 valgrind 来准确找出发生分段错误的位置。只需在程序名称或执行程序的方式之前键入 valgrind。例如,如果您使用以下命令执行程序:

你好-打印

改为发出以下命令:

valgrind hello -print

【讨论】:

以上是关于C++ 分段错误 OpenCV的主要内容,如果未能解决你的问题,请参考以下文章

分段错误 Opencv linux c++

简单的 C++ OpenCV imshow 示例因分段错误而崩溃

为 OpenCV 的 C++ createTrackbar 运行 C 包装器时出现编译分段错误(核心转储)

分段错误原因未知Opencv

OpenCV中的分段错误

OpenCV 4.2.0 FileStorage 分段错误