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

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

ただいまの
回答率

90.34%

  • C

    4005questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

連続する数値を検出するアルゴリズムを教えてください

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 2,222

kuma_dansyaku

score 12

 はじめに

いつもお世話になっています。
表題の件について質問があります。

C言語でQRコードを実装しているのですが、その実装の一部にマスクの失点を計算する処理があります。
簡単に言いますと、「黒と白で構成されているQRコードにおいて同じ色が連続で続くと良くないので、
その様なパターンを減点してより点数の高いパターンを採用する」と言う処理です。

処理そのものの実装は全く難しくないのですが、連続するモジュールの算出方法を少し簡単に出来ないかな?
と思い質問しました。

#define WHITE_MODULE (0x00)    // この値を変える事で分かりやすくなるなら変更してもOK
#define BLACK_MODULE (0xFF)    // この値を変える事で分かりやすくなるなら変更してもOK
typedef unsigned char BYTE;
int ErrPointLine(BYTE *pQRdata, int version)
{
    int Eret=0; /* エラーポイント */
//  int line_max = _qr_code_info[version].side_module_num;
    int line_max = 40;  // 暫定で 40 固定

    // 列
    for( int h=0 ; h < line_max ; h++ ){
        int blacks = 0;
        int whites = 0;
        const BYTE *pHead = pQRdata + (line_max * h);
        for(int n=0 ; n < line_max ; n++ ){
            BYTE LineCol = *(pHead + n);

            if(LineCol == BLACK_MODULE){
                blacks++;
                whites=0;
            }
            else if(LineCol == WHITE_MODULE){
                blacks=0;
                whites++;
            }

            // 同色が5つ続くなら+3の失点
            if(blacks == 5 || whites == 5){
                Eret += 3;
            }
            else if(blacks > 5 || whites > 5){
                // 以後続くたびに+1の失点
                Eret++;
            }
        }
    }
    printf("Total Error Point = %d\n", Eret);

    return Eret;
}

良い知恵がありましたらぜひ教えてください。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

こんにちは。

大差ないですが、私はこのような時次のようなアルゴリズムで実装します。

  • 最後の状態を記録する変数を1つ設ける:現在の行の先頭値で初期化
  • カウンタを1つ設ける:1で初期化
  • 行の先頭の次から行の最後までループ
  • 最後の状態と現在の値が同じなら、++カウンタ
    そうでないなら、カウンタ=1
  • カウンタの値に応じた処理

【追記】
ソースを書ける方なら分かってくれるかなと思って手抜きしました。
下記イメージです。(コンパイルしてませんのでエラーがでたら悪しからず。)
列数が0の時は異常動作します。現在は列数=行数=line_maxですが、もし列数と行数を異なるパラメータにする時はパラメータ・チェックが必要です。

#define WHITE_MODULE (0x00)    // この値を変える事で分かりやすくなるなら変更してもOK
#define BLACK_MODULE (0xFF)    // この値を変える事で分かりやすくなるなら変更してもOK
typedef unsigned char BYTE;
int ErrPointLine(BYTE *pQRdata, int version)
{
    int Eret=0; /* エラーポイント */
//  int line_max = _qr_code_info[version].side_module_num;
    int line_max = 40;  // 暫定で 40 固定

    // 列
    for( int h=0 ; h < line_max ; h++ ){
        int counter= 1;
        const BYTE *pHead = pQRdata + (line_max * h);
        BYTE last = *pHead;
        for(int n=1 ; n < line_max ; n++ ){
            BYTE LineCol = *(pHead + n);

            if(LineCol == last ){
                counter++;
            }
            else {
                last=LineCol;
                counter=1;
            }

            // 同色が5つ続くなら+3の失点
            if(counter == 5){
                Eret += 3;
            }
            else if(counter> 5){
                // 以後続くたびに+1の失点
                Eret++;
            }
        }
    }
    printf("Total Error Point = %d\n", Eret);

    return Eret;
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/03/22 09:40

    回答ありがとうございます。

    申し訳ありません。
    自分の知識不足でどうやればいいのか理解できませんでした。

    回答して頂いたのに申し訳ありませんでした。

    キャンセル

  • 2017/03/22 15:14

    質問者さんのソースにおける blacks, whites を、「別に分ける必要ないよね」という視点からの回答だと思います。
    直前の色と同じ→カウントアップ
    直前の色と違う→カウントクリア
    とすれば、「同じ色が何度つづいた」を知ることができるということですね

    キャンセル

  • 2017/03/23 21:15

    なるほどわかりました。
    ありがとうございます。

    ヒントを頼りに自己解決に書いた解釈で良かったとみたいですね。
    補足ありがとうございました。

    キャンセル

0

XOR(排他的論理和)を使って前後が同じかどうかを判定する様に変更しました。

// 列
for( int y=0 ; y < line_max ; y++ ){
    const BYTE *pHead = pQRdata + (line_max * y);  // 1ライン毎の先頭アドレス
    for(int x=1 , cnt=1; x < line_max ; x++ ){
        if( pHead[x-1]^pHead[x] ){
            cnt=1;
            continue;
        }
        cnt++;
        // 同色が5つ続くなら+3の失点
        if(cnt == 5){
            Eret += 3;
        }
        else if(cnt > 5){
            // 以後続くたびに+1の失点
            Eret++;
        }
    }
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • C

    4005questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。