0

次のコードのアイデアは、イメージをキャンバスにゆっくりと「ペイント」する一連の「放浪者」オブジェクトを用意することです。問題は、このコードが正方形の画像でのみ機能しているように見えることです (コードでは、正方形の画像は「非表示」として識別され (「ペインター」によって公開されるため)、「UncoverTest」というファイルから読み込まれます)。 .png")、私には不思議な長方形のものではありません。正方形以外を操作しようとすると、セグメンテーション違反エラーが発生します。私が知る限り、ループに入ってエージェント型のベクトルを反復処理すると (行で)、セグメンテーション違反エラーが発生します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);
  }
}

正方形の画像のみでこのエラーがどのように発生し、どのように問題を解決できるかを誰かに説明してもらえますか?

4

2 に答える 2

0

Linux 環境にいる場合は、valgrind を使用して、セグメンテーション違反が発生している場所を正確に見つけることができます。プログラムの名前、またはプログラムの実行方法の前に valgrind と入力するだけです。たとえば、次のコマンドでプログラムを実行するとします。

こんにちは-印刷

代わりに次のコマンドを発行します。

valgrind こんにちは-印刷

于 2014-04-12T10:56:49.667 に答える
0

私はあなたのコードを完全には理解していませんが、あなたの最後のコメント「キャンバスのステッピング」に従って、「非表示」の両方で範囲外のデータにアクセスしようとする状況がいくつかあることがわかると思いますマットと「イメージ」マット。

恐れて、私は提案しか提供できません

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() を使用します。したがって、ここでもエラーが発生すると確信しています。location は、hidden.cols() および hidden.rows() から派生する必要があります。

一見しただけでしたが、 getLocation() が返す値の周りにいくつかのチェックを入れ、そのような値がマット行列からアクセスできるかどうかを確認します。

さらに、完全にはわかりませんが、場所を2つの異なる方法で使用していると思いますが、場所が 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 は画像の幅です。

それがあなたを正しい軌道に乗せることを願っています。

于 2012-12-31T00:50:44.090 に答える