合計 昨日 今日

OpenCV 色の検出

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: aaaa
[URL]
Date: 2017年10月05日(木) 14:06
No: 1
(OFFLINE)

 OpenCV 色の検出

こんにちは。
今、わたしは赤色と青色だけを抽出することができるプログラムを作りました。(赤色のみ黒で塗りつぶした画像、青色のみ画像を塗りつぶした画像を表示)

次に私はこの画像が赤色か青色かを判断するプログラム(printfで赤、青を表示する)を作りたいと考えています。

しかしどうのようにしたらよいか全くわからず、ご助言をお願いした次第でございます。

コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using namespace cv;
 
int main(int argc, const char *argv[])
{
    /*genga*/
    Mat src_image = imread("big.jpg");
    namedWindow("genga");
    imshow("genga", src_image);
   
    int width = src_image.cols;
    int height = src_image.rows;
   
    /*HSV*/
    Mat hsv_image;
    cvtColor(src_image, hsv_image, CV_BGR2HSV);
   
    uchar hue, sat, val;
    Mat red_image = Mat(Size(width, height),CV_8UC1);
    Mat blue_image = Mat(Size(width, height),CV_8UC1);
   
    for(int y=0; y<height; y++)
        for(int x=0; x<width; x++)
        {
            /*H,S,V*/
            hue = hsv_image.at<Vec3b>(y, x)[0];
            sat = hsv_image.at<Vec3b>(y, x)[1];
            val = hsv_image.at<Vec3b>(y, x)[2];
           
            /*red_detect*/
            if((hue<10 || hue>170) && sat>45)
                red_image.at<uchar>(y, x) = 0;
           
            else
                red_image.at<uchar>(y, x) = 255;
               
            /*blue_detect*/
            if((hue>75 && hue<90) && sat>60)
                blue_image.at<uchar>(y, x) = 0;
           
            else
                blue_image.at<uchar>(y, x) = 255;
       
    }
   
    namedWindow("red_detect");
    imshow("red_detect", red_image);
   
    namedWindow("blue_detect");
    imshow("blue_detect", blue_image);
   
    if(red_image)
   
   
   
    waitKey(0);
    destroyAllWindows();
    return 0;
}

Name: aaaa
[URL]
Date: 2017年10月05日(木) 14:13
No: 2
(OFFLINE)

 Re: OpenCV 色の検出

度々すいません。
自分では、「red_image.at<uchar>(y, x) = 0 ならばflagを1にする」→「flagが1ならばprintfで赤と言う」
とすればできると思ったのですがうまく行きません

どうしたらよいのでしょうか。。。
お願いしたします

Name: asd
[URL]
比類なきプログラマー(70,671 ポイント)
Date: 2017年10月05日(木) 15:21
No: 3
(OFFLINE)

 Re: OpenCV 色の検出

aaaa さんが書きました:次に私はこの画像が赤色か青色かを判断するプログラム(printfで赤、青を表示する)を作りたいと考えています。


aaaa さんが書きました:自分では、「red_image.at<uchar>(y, x) = 0 ならばflagを1にする」→「flagが1ならばprintfで赤と言う」
とすればできると思ったのですがうまく行きません


プログラム内部の話をする前に判定方法について素朴な質問なのですが、
与えられる画像は「赤一色」「青一色」「赤でも青でもない」の3種類の画像と考えてよいでしょうか?
というのも、与えられた画像を「赤」、「青」と判別する基準が不明確なのでそこを明確にしたいなと思いまして。

例えば「赤一色」の画像であれば赤成分が1ピクセルでもあれば「赤画像である」と判別できるので
赤成分の有無をフラグで保持すれば判別できますが、
「赤も青も混在した画像」が渡された場合には赤成分も青成分もあるのに「赤画像である」と誤判別される可能性も出てきます。

この場合には赤成分と青成分のより多い方を優勢とみなす方法もありますが、
さらに厄介なのが「紫色一色」の画像のように赤成分も青成分も含まれているものの人間が見ると赤でも青でもない画像を与えた場合など
判別方法をどのようにするのか、与える画像は制限して考えてよいのかを教えてください。

一旦ここでは「赤一色」「青一色」のみの画像しか与えない前提で提示されているプログラムを見てみました。
提示されているプログラムでは赤と青のフラグはないようですが、
どのような処理を書かれて、どのような画像を与えたらどう判定されると考え、実際はどうだったのでしょうか?

実際に動かなかったというプログラムも提示されておらず、与えた画像と期待した結果、実際の結果も提示されていないので、
「うまく行きません」だけでは何に困っているのかこちらでもよくわかりません。

赤フラグと青フラグを追加して、どのような結果を期待し、実際はどうだったのかを提示していただけると
より詳細な助言がもらえるかと思いますよ。
Advanced Supporting Developer
無理やりこじつけ(ぉ

Name: aaaa
[URL]
Date: 2017年10月05日(木) 15:26
No: 4
(OFFLINE)

 Re: OpenCV 色の検出

ご返信ありがとうございます。

とても納得させられました。
自分の中でもまとまっていないので、まとまり次第追記させていただきます。

また、私は信号の色を判断したいと考えています。
画像は限りなく信号機のみを写している画像を使う予定なので、画像は「上半分が赤で下半分が黒」、「上半分が黒、下半分が青」というような画像のつもりです。

Name: aaaa
[URL]
ぴよぴよ(680 ポイント)
Date: 2017年10月05日(木) 16:00
No: 5
(OFFLINE)

 Re: OpenCV 色の検出

先ほど、信号機の画像を使うと宣言しましたが、まず第一歩として、赤色単色の画像を「赤色」と言わせたいです。
そこで、このようなコードを作りました。
赤であればflag_redが1になり、赤色というというイメージです
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using namespace cv;
 
int main(int argc, const char *argv[])
{
    /*genga*/
    Mat src_image = imread("red.jpg");
/*  namedWindow("genga");
    imshow("genga", src_image);
*/ 
    int width = src_image.cols;
    int height = src_image.rows;
   
    /*HSV*/
    Mat hsv_image;
    cvtColor(src_image, hsv_image, CV_BGR2HSV);
   
    uchar hue, sat, val;
    Mat red_image = Mat(Size(width, height),CV_8UC1);
    Mat blue_image = Mat(Size(width, height),CV_8UC1);
   
    int flag_red = 0;
    int flag_blue = 0;
   
    for(int y=0; y<height; y++)
        for(int x=0; x<width; x++)
        {
            /*H,S,V*/
            hue = hsv_image.at<Vec3b>(y, x)[0];
            sat = hsv_image.at<Vec3b>(y, x)[1];
            val = hsv_image.at<Vec3b>(y, x)[2];
           
            /*red_detect*/
            if((hue<10 || hue>170) && sat>45)
                red_image.at<uchar>(y, x) = 0;
               
                flag_red = 1;
               
            else
                red_image.at<uchar>(y, x) = 255;
               
        /*      flag_blue = 1;
        */     
            /*blue_detect*/
        /*  if((hue>75 && hue<90) && sat>60)
                blue_image.at<uchar>(y, x) = 0;
           
            else
                blue_image.at<uchar>(y, x) = 255;
                /*flag = 1;*/
    }
   
/*  namedWindow("red_detect");
    imshow("red_detect", red_image);
   
    namedWindow("blue_detect");
    imshow("blue_detect", blue_image);
*/
    if(flag_red=1){
    printf("red\n");
    }
   
   
    waitKey(0);
    destroyAllWindows();
    return 0;
}


しかし、こちらはこのようなエラーが出てしまいました。
コード[C++]: 全て選択
1
2
3
redbluedetect.cpp:55:4: error:else’ without a previous ‘if
    else
    ^


私はこのエラーを調べたところ意味が理解できませんでした。
また、elseの下ならば、flagが1になることは確認できたのですが、この違いがよくわからないのです。

このプログラムでも、赤じゃないから青です。
とは言えそうなのですが、できれば赤だから赤と言わせたいです。

Name: asd
[URL]
比類なきプログラマー(70,671 ポイント)
Date: 2017年10月05日(木) 16:12
No: 6
(OFFLINE)

 Re: OpenCV 色の検出

aaaa さんが書きました:また、私は信号の色を判断したいと考えています。
画像は限りなく信号機のみを写している画像を使う予定なので、画像は「上半分が赤で下半分が黒」、「上半分が黒、下半分が青」というような画像のつもりです。


追記ありがとうございました。なるほど信号機でしたか。
そういうことであれば、背景やら信号機の灯火以外の余計な部分は一旦考えないものとして、
与えられた画像の赤成分、青成分を数えて多い方をその画像の色だと判定してもよいかもですね。
(赤と青が同時に点灯することはないものとして)

その場合だとフラグ方式よりも、赤と青の各成分量(ピクセル数)をカウントするようにした方がよいのかもです。
いずれにせよ判別方法がまとまるのをお待ちします(*´ヮ`)

…と書いていたら追記があったのでそちらにも返信します。

aaaa さんが書きました:しかし、こちらはこのようなエラーが出てしまいました。
コード[C++]: 全て選択
1
2
3
redbluedetect.cpp:55:4: error:else’ without a previous ‘if
    else
    ^



提示されているプログラムのif文を見るとブロック{}で囲まれていないため、
判定分の直後の処理は1文しか書けない状態になっています。
それにもかかわらずif文の後に複数の文を書いた後でelse節を書いたために、
「elseに対応するifが見つからないよ!」とエラーを出されています。

当該部分だけを抜き出すと以下の部分です。
if((hue<10 || hue>170) && sat>45) の後にflag_red=1;が追記されたために、
if文がtrueだった時に処理する内容が複数の文になってしまいました。
{}で囲わない場合にはifやelseの後には1文しか書けないので、
エラーになっているものと思います。

aaaa さんが書きました:
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
            /*red_detect*/
            if((hue<10 || hue>170) && sat>45)
                red_image.at<uchar>(y, x) = 0;
               
                flag_red = 1;
               
            else
                red_image.at<uchar>(y, x) = 255;



ですので解決策としては以下のようにifやelseの処理部分を{}で囲んでブロックにしてあげるとよいかと思います。

コード[C++]: 全て選択
1
2
3
4
5
6
7
8
            /*red_detect*/
            if((hue<10 || hue>170) && sat>45)
            {
                red_image.at<uchar>(y, x) = 0;
                flag_red = 1;
            }
            else
                red_image.at<uchar>(y, x) = 255;


これで期待した動きになったでしょうか?
不明な点があれば遠慮なく聞いてくださいね(*´ヮ`)

aaaa さんが書きました:このプログラムでも、赤じゃないから青です。
とは言えそうなのですが、できれば赤だから赤と言わせたいです。


確かに消去法で「赤じゃないから青」と判定してしまうと、
「黄色信号」の場合や「停電で赤も青も消灯している信号」に確実に誤判定しますので、間違いなく赤だ(or青だ)という判定にしたいですよね。
Advanced Supporting Developer
無理やりこじつけ(ぉ

Name: aaaa
[URL]
ぴよぴよ(680 ポイント)
Date: 2017年10月05日(木) 16:22
No: 7
(OFFLINE)

 Re: OpenCV 色の検出

素早い変身体へなりがとうございます。

まずは、ifのあとに{}の説明とご指示のため、解決することができました!
わかりやすい説明でとても感謝しています。
ありがとうございます。

また、ピクセルをカウントしたほうが良いという助言にも大変有り難みを感じています。
実際に赤信号の時に別のもの写ったらどうしようと悩んでいたので、この助言を元に一度プログラムを作ってい見たいと思います
本当にありがとうございます

Name: asd
[URL]
比類なきプログラマー(70,671 ポイント)
Date: 2017年10月05日(木) 18:10
No: 8
(OFFLINE)

 Re: OpenCV 色の検出

aaaa さんが書きました:素早い変身体へなりがとうございます。

まずは、ifのあとに{}の説明とご指示のため、解決することができました!
わかりやすい説明でとても感謝しています。
ありがとうございます。

また、ピクセルをカウントしたほうが良いという助言にも大変有り難みを感じています。
実際に赤信号の時に別のもの写ったらどうしようと悩んでいたので、この助言を元に一度プログラムを作ってい見たいと思います
本当にありがとうございます


本題については無事に解決したようでよかったです(*´ヮ`)

ちなみに解決した場合には送信ボタンの横に「解決!」というチェックボックスがありますので、
そこにチェックを入れた状態で解決報告を投稿すると解決したことが表示されますので、
解決した場合には「解決!」へのチェックも忘れないようお願いします。

Offtopic :
一旦は信号機のみが写っている画像としているので問題ないとは思いますが、
提示されているように信号機以外のものが写っている場合(たとえが背景に赤い風船が写ってたりとか)には
単純なピクセルカウントだけですと誤判定の可能性も出てきます。

第一弾の判別プログラムが完成したら、実用的な条件(別のものが写っているとか)を付与していき
そのような場合にどう対応するのかを考えて精度を上げていくのかなと思います。
そのあたりを考えるのが面白味だと思うので、引き続き頑張ってください(*´ヮ`)
Advanced Supporting Developer
無理やりこじつけ(ぉ

Name: aaaa
[URL]
ぴよぴよ(680 ポイント)
Date: 2017年10月09日(月) 15:09
No: 9
(OFFLINE)

 Re: OpenCV 色の検出

[解決!]

失礼いたしました。
おかげさまで解決することができました。
ありがとうございました。


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[19人]