質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

C言語で画像処理におけるラベリング処理をしようとすると実行エラーがでる

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 943

sabo-rino33

score 7

前提・実現したいこと

C言語で画像処理の際に使用するラベリング関数を作っています。
int labeling(char* output,int bright);の関数部分でラベリング処理を行おうとしています。

同じフォルダーに星の画像を入れ星が何個あるかを数えるプログラムを作っています。
(field1.bmp)が星の画像です。

発生している問題・エラーメッセージ

mainメソッドなどは問題ないのですがlabeling関数の部分で実行エラーが出てしまいます。
0,1に二値化された場所にラベリング処理をしている際に、コンパイルは成功するのですが実行エラーが起き動作が停止してしまいます。(1)以降のif文をコメントすると一応実行はできるようになるので、
その近辺でバグが起きているのだと思いますがデバッグの方法が分かりません。

エラーメッセージですが、「動作が終了しました」と出てしまい、プログラムが停止してしまいます

該当のソースコード

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>

#define NX 2048    //Image size X
#define NY 2048 //Image size Y
#define HEADER_SIZE 300 //maximum header size

void readImageFile(char*, char*, char*, int, int, int*);
void writeImageFile(char*, char*, char*, int, int, int);
int labeling(char* ,int);

void main(int argc, char *argv[])
{
    char *input, *output, *header;
    int hSize;
    int j,i;            //ループ変数
    int cnt = 0;            //星の数を数える変数
    int sepbright = 10;    //星を分ける大きさ(ここに二値化の最善の値を入れる)
    int bright = 1;        //星の返す色

    input = (char*)malloc(NX*NY * 1);
    output = (char*)malloc(NX*NY * 1);
    header = (char*)malloc(HEADER_SIZE);

    // read image file
    readImageFile("field1.bmp", input, header, NX, NY, &hSize);

//    getchar();            //なくてもいい(実行時returnですすむ)

    //Image processing  ここ変える
    for (j = 0; j < NY; j++) {
        for (i = 0; i < NX; i++) {
            output[j*NX + i] = input[j*NX + i];

            //適当な二値化
            if(output[j*NX + i] >=sepbright){
                output[j*NX + i] = bright;//bright は1設定
            }else if(output[j*NX + i] <sepbright){
                output[j*NX + i] = 0;
            }

        }//printf("%d ",j);
    }

    cnt = labeling(output,bright);
    printf("星の数:%d",cnt);
    // write image file
    writeImageFile("output1.bmp", output, header, NX, NY, hSize);

    free(header);
    free(output);
    free(input);

}


//jは縦、iは横
//output:読み込んだ画像,
//bright:二値化された場所が0か1を判定するための引数
int labeling(char* output,int bright){
    int* look;            //ルックアップカウンタ
    look =(int *)malloc(2000);
    int lookcnt =0;        //lookを書き換えたやつ
    int num =2;            //ラベリングした回数の変数
    int min = num;        //最小の番号を振り割るための変数
    int j,i,k;            //for文変数

    for (j = 0; j < NY; j++) {
        for (i = 0; i < NX; i++) {
            //二値化されたものがbrightであれば
            if(output[j*NX + i] == bright){
                //左上、上、右上、左の画素番号がすべて0なら
                //numの値を振り分けていく
                //(1)ここ以下のif文でエラー?
                if(output[(j-1)*NX+i-1]==0 && output[(j-1)*NX+i]==0 &&
                    output[(j-1)*NX+i+1] ==0 && output[j*NX+i-1]==0)
                {
                    output[j*NX + i]=num;    //numは2から
                    look[num]=num;
                    num++;
                }
            //左上、上、右上、左の画素番号のうち0以外が複数あるなら
                else{
                    if(output[(j-1)*NX+i-1] != 0 && output[(j-1)*NX+i-1]<min){
                        min = output[(j-1)*NX+i-1];    
                        //look[num]の値と左上の値が違うならlookを書き換える
                        if(look[num] != output[(j-1)*NX+i-1]){
                            look[num] = output[(j-1)*NX+i-1];
                            lookcnt++;
                        }
                    }

                    else if(output[(j-1)*NX+i] != 0 && output[(j-1)*NX+i]<min){
                        min = output[(j-1)*NX+i];

                        //look[num]の値と上の値が違うならlookを書き換える
                        if(look[num] != output[(j-1)*NX+i]){
                            look[num] = output[(j-1)*NX+i];
                            lookcnt++;
                        }

                    }

                    else if(output[(j-1)*NX+i+1] != 0 && output[(j-1)*NX+i+1]<min){
                        min = output[(j-1)*NX+i+1];

                        //look[num]の値と右上の値が違うならlookを書き換える
                        if(look[num] != output[(j-1)*NX+i+1]){
                            look[num] = output[(j-1)*NX+i+1];
                            lookcnt++;
                        }

                    }
                    else if(output[j*NX+i-1] != 0 && output[j*NX+i-1]<min){
                        min = output[j*NX+i-1];

                        //look[num]の値と左の値が違うならlookを書き換える
                        if(look[num] != output[j*NX+i-1]){
                        look[num] = output[j*NX+i-1];
                        lookcnt++;
                        }
                    }
                    output[j*NX+i]=min;
                }
            }
        }
    }

    return num-2-lookcnt;
}


void readImageFile(char* fileName, char* input, char* header, int xsize, int ysize, int *headerSize)
{
    FILE *fp;
    int imageSize = xsize*ysize * 3;
    int j;

    fp = fopen(fileName, "rb");
    if (fp == NULL) {
        fprintf(stderr, "File open error: %s", fileName);
        exit;
    }

    fseek(fp, 0, SEEK_END);
    int fileSize = ftell(fp);
    *headerSize = fileSize - imageSize;
    printf("%d %d %d\n", imageSize, fileSize, *headerSize);

    fseek(fp, 0, SEEK_SET);

    fread(header, *headerSize, 1, fp);    //read header

    for (j = 0; j < xsize*ysize; j++) {
        input[j] = fgetc(fp);
        fgetc(fp);
        fgetc(fp);
    }
}

void writeImageFile(char* fileName, char* input, char* header, int xsize, int ysize, int headerSize)
{
    FILE *fp;
    int imageSize = xsize*ysize * 3;
    int j;

    fp = fopen(fileName, "wb");
    if (fp == NULL) {
        fprintf(stderr, "File open error: %s", fileName);
        exit;
    }

    fwrite(header, headerSize, 1, fp);    //read header

    for (j = 0; j < xsize*ysize; j++) {
        fputc(input[j], fp);
        fputc(input[j], fp);
        fputc(input[j], fp);
    }
}

修正した箇所

(1)以下の処理をコメントしたときは実行が通ったので、
それ以降が間違っていそうなのですが修正する方法がわかりません。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • pepperleaf

    2019/07/31 00:34

    > コンパイルは成功するのですが実行エラーが起き
    それを普通、バグと言います。
    どんなエラーが出ているか、具体的に記述しましょう。(エラーメッセージはそのまま)
    また、コードは、コードタグで括ってください。"<code>" アイコン。

    キャンセル

  • sabo-rino33

    2019/07/31 01:24

    内容が伝わりにくく申し訳ございません。
    まだ伝わりづらいでしょうか。

    キャンセル

回答 2

checkベストアンサー

0

ソースを読んでられないので。

実行時エラーの殆どは、確保した領域の外をアクセスしている、ために起こるものです
がんばって、確保サイズ内に収まっているのかをチェックするしかないですね。

で、ちょっと気になったところを指摘しておきます

    look =(int *)malloc(2000);

mallocで指定するのはバイト数ですんで、ここでのintのサイズを4バイトだとすると、
look には500個分だけの領域しか割り当てられてませんがそこらへんは大丈夫でしょうか。

これだけのサイズのコードを書くなら、VisualStudioとかEclipseとかのデバッグできる環境を整えましょう。
任意の行で止めて変数のナカミを確認したり、1行づつ実行したりすることもできます。
これで、アテずっぽでコードを書かなくて済むようになります

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

開示されているソースがコピー&ペーストのものだとすると

//二値化されたものがbrightであれば
if(output[j*NX + i] = bright){  

条件判断しているつもりのif文で、評価する対象に別の値を代入しています。
充分誤動作する可能性があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/31 02:03

    回答ありがとうございます。確かに条件判断のところを代入していました。
    ですが、まだ実行時にエラーが出てしまい、どうしたらいいでしょうか。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る