

### 【追記】

皆様コメントありがとうございます。  
ご指摘いただきました場所を修正したところ強制終了は回避できるようになりました。本当にありがとうございます。  
しかしプログラムは上手く座標を渡してくれませんでした。  
コメントを参考にプログラムを書き直したところはコメントアウトして新しいものを載せておきます。

[![入力画像1\(img\)](https://i.stack.imgur.com/LOz5t.png)](https://i.stack.imgur.com/LOz5t.png)  
[![入力画像2\(temp\)](https://i.stack.imgur.com/WbqnX.png)](https://i.stack.imgur.com/WbqnX.png)

上のを入力したところ返ってきたマッチングの始点となる座標は（y,x）=
(45,204)でした。（画像１の画素は225×225であり明らかに目的とする画素より遠い）  
プログラムの数式が間違っているのかそもそもアルゴリズムの使い方が間違っているのかわかりません。

### 前提・実現したいこと

C言語とGCCを使っています。  
ZNCC（テンプレートマッチング）を使い類似度の一番高い一番最初の画素の特定を輝度情報をもとに実装したいのですが、コンパイルは通るものの探索がある一定の位置でプログラムが強制終了してしまいます。//強制終了は解決しました！ありがとうございます！

画像のピクセルの位置は一次元の配列になっています。  
imgは元の大きい画像をtempはテンプレート画像を表しています。  
NCC関数内で元画像の（x,y）を起点とする類似度を求め、templatematching関数で類似度が一番高かった座標を求めています。

私はプログラミング初心者でつたないコードしか書けませんがよろしくお願いいたします。

### 該当のソースコード

[code]

    typedef struct{
      unsigned int width;
      unsigned int height;
      Rgb *rgb;
      Hsv *hsv;
    }Image;
    
    int templatematching(Image *img, Image *temp)
    {
      int i, j, k, x, y, index;
      double ncc=-1.0, n, mu=0;
    
      for(k=0; k<temp->height*temp->width; k++){
        mu += temp->hsv[k].v;
      }
      mu = mu / k;
    
      for(i=0; i<img->height; i++){
        for(j=0; j<img->width; j++){
    
          if(ncc < (n = NCC(img, temp, j, i, mu)))
          {
            ncc = n;
            y = i;
            x = j;
         }
        }
      }
    
      index = y*img->width + x;
      return index;
    
    }
    
    double NCC(Image *img, Image *temp, int x, int y, double mu)
    {
      int i, j, k=0, index;
      double bunsi=0, bunbo1=0, bunbo2=0;
      double ncc, mi=0;
    
      if(img->width - x < temp->width / 3 || img->height - y < temp->height / 3) {return -2.0;}//この方がマッチングがうまくいくのかと思い書き加えました
    
      index = y * img->width + x;
    
      for(i=0; i<temp->height-1; i++){
        for(j=0; j<temp->width-1; j++){
          if(((y + (i * img->width)) > img->height) || (x + j > img->width) ) break;
          mi += (img->hsv[index + i * img->width + j].v);
          k++;
        }
      }
    
      mi = mi / k;
    
        for(i=0; i<temp->height-1; i++){
            for(j=0; j<temp->width-1; j++){
    //        if((y + i * img->width > img->height) || (x + j > img->width) ) break;
            if((y + i) > img->height || (x + j > img->width) ) break;
            bunsi += (img->hsv[index + i * img->width + j].v-mi) * (temp->hsv[i*temp->width+j].v-mu);
    //       bunbo1 += sqrt((img->hsv[index + i * img->width + j].v -mi)* (img->hsv[index + i * img->width + j].v -mi));
    //       bunbo2 += sqrt((temp->hsv[i*temp->width+j].v- mu) * (temp->hsv[i*temp->width+j].v- mu));
              bunbo1 += fabs(img->hsv[index + i * img->width + j].v - mi);
              bunbo2 += fabs(img->hsv[index + i * img->width + j].v - mi);
      
            }
        }
    
        if(bunbo1 == 0 || bunbo2 == 0 ) return -2.0;　//念のため分母が０のときは―2を返す
    
        ncc = bunsi / (bunbo1 * bunbo2);
    
        return ncc;
    }
    
[/code]


CC BY-SA 4.0
2020-02-04T08:31:10.427
62766
2022-08-18T16:07:45.823
2020-06-17T08:14:45.997
-1
37712
question
c
画像処理のZNCCをC言語で実装したいが、強制終了してしまう


`if((y + i) > img->height || (x + j > img->width) ) break;` で範囲外アクセスを修正した結果、  
画像の端では集計する面積が変化して尺度として不適切になってるようです。  
単純にはtempの範囲がimgの外にはみ出さない範囲でだけを対象にすれば自然な結果になります。  
画像の一部でもマッチさせたい場合は何か別の尺度を設計する必要があると思います。

[code]

    double NCC(Image *img, Image *temp, int x, int y, double mu)
    {
      // テンプレート画像がマッチする画像の範囲外の場合に -2 を返す
      if (x + temp->width >= img->width)
        return -2.0;
      if (y + temp->height >= img->height)
        return -2.0;
    
      const int index = y * img->width + x;
    
      double mi = 0;
      int k = 0;
      for (int i = 0; i < temp->height - 1; i++) {
        for (int j = 0; j < temp->width - 1; j++) {
          if (((y + (i * img->width)) > img->height) || (x + j > img->width)) break;
          mi += (img->hsv[index + i * img->width + j].v);
          k++;
        }
      }
    
      mi = mi / k;
    
      double bunsi = 0, bunbo1 = 0, bunbo2 = 0;
      for (int i = 0; i < temp->height - 1; i++)
      {
        for (int j = 0; j < temp->width - 1; j++)
        {
          bunsi += (img->hsv[index + i * img->width + j].v - mi) * (temp->hsv[i * temp->width + j].v - mu);
          bunbo1 += fabs(img->hsv[index + i * img->width + j].v - mi);
          bunbo2 += fabs(img->hsv[index + i * img->width + j].v - mu);// mi から mu に修正
        }
      }
    
      if (bunbo1 == 0 || bunbo2 == 0)
        return -2.0; //念のため分母が０のときは―2を返す
    
      double ncc = bunsi / (bunbo1 * bunbo2);
    
      return ncc;
    }
    
[/code]


CC BY-SA 4.0
2020-03-16T02:52:12.850
63880
2020-03-16T02:52:12.850
241
62766
answer