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

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

ただいまの
回答率

90.40%

  • C++

    3957questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • OpenCV

    1321questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

OpenCVで動画の読み込みがうまくできません。

受付中

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,100

sh1208

score -6

以前別のプログラムで動画の読み込みができましたが、今現在取り組んでいるプログラムではうまくいきません。
言語はC++でopencv2.4.9を使用しています。
Os windows8.1 visual studio2013を使っています。
よろしくお願いします。

エラーメッセージ

OpenCV Error: Assertion failed (udata < (uchar*)ptr && ((uchar*)ptr - udata) <= (ptrdiff_t)(sizeof(void*)+16)) in cv::fastFree, file C:\builds\2_4_PackSlave-win32-vc12-shared\opencv\modules\core\src\alloc.cpp, line 78

{
    if(ptr)
    {
        uchar* udata = ((uchar**)ptr)[-1];
        CV_DbgAssert(udata < (uchar*)ptr &&
               ((uchar*)ptr - udata) <= (ptrdiff_t)(sizeof(void*)+CV_MALLOC_ALIGN));
        free(udata);
    }
}
コード
#include <opencv2/opencv.hpp>
//静的リンクライブラリの指定
#include <opencv2/opencv_lib.hpp>

#include "Classifier.h"
#include "IntegralHistogram.h"
#include "MeanShift.h"
#include "Common.h"


//画像を扱う構造体の宣言
IplImage* imgSource = NULL;            //原画像
IplImage* imgResult = NULL;            //人検出結果
IplImage* imgGray = NULL;            //グレイスケール画像



//クラス
CClassifier                    ob_CL;    //Real AdaBoostによる識別
CIntegralHistogram            ob_IH;    //Integral HistogramによるHOG特徴量算出
CMeanShift                    ob_MS;    //MeanShiftによる検出ウィンドウの統合



int main(){
    int i, j, l;
    int frame = 0;
    CvCapture *capture = NULL;    //    カメラキャプチャ用の構造体

    //出力ウィンドウの作成
    char* winOriginal = "OutputImage";


    cvNamedWindow(winOriginal, CV_WINDOW_AUTOSIZE);


    //検出ウィンドウのパラメータ
    int window_width = INIT_WINDOW_X;
    int window_height = INIT_WINDOW_Y;
    int window_count = 0;
    int window_ture_count = 0;
    int tcount = 0;
    double scale;

    //HOG特徴量の配列
    double feature[FEATURE];


    //    動画ファイルを開く
    if ((capture = cvCaptureFromFile("C:\\opencv\\sources\\samples\\c\\tree.avi")) == NULL) {
        //    ファイルが見つからなかった場合
        printf("ファイルが見つかりません\n");
        exit(1);
    }

    imgSource = cvQueryFrame(capture);

    //領域確保
    imgGray = cvCreateImage(cvGetSize(imgSource), IPL_DEPTH_8U, 1);


    //aviファイル設定
    double fps = 25.0;
    CvVideoWriter* VideoWriter = cvCreateVideoWriter("C:\\opencv\\sources\\samples\\c\\result.avi", -1, fps, cvGetSize(imgSource), 1);

    //カラー画像からグレイスケール画像へ変換
    cvCvtColor(imgSource, imgGray, CV_BGR2GRAY);


    //初期化
    ob_IH.CreateGradLUT();
    ob_CL.init();
    ob_MS.Init(imgSource);
    ob_IH.Init(imgGray);
    cvReleaseImage(&imgSource);

    //人検出開始
    while (1){
        //画像の読み込み
        imgSource = cvQueryFrame(capture);
        if (imgSource == NULL)
            exit(1);
        printf("frame -> %d\n", frame);

        //積分画像の初期化
        ob_IH.ClearIH();

        //    画像サイズを保存
        CvSize imageSize = cvGetSize(imgSource);

        //領域確保
        imgResult = cvCreateImage(imageSize, IPL_DEPTH_8U, 3);

        //カラー画像からグレイスケール画像へ変換
        cvCvtColor(imgSource, imgGray, CV_BGR2GRAY);

        //勾配方向と勾配強度,積分画像の算出
        ob_IH.CreateIntegralHistogram(imgGray);

        //原画像のコピー
        memcpy(imgResult->imageData, imgSource->imageData, imgSource->width * imgSource->height * 3);

        //パラメータの初期化
        window_width = INIT_WINDOW_X;
        window_height = INIT_WINDOW_Y;
        window_count = 0;
        window_ture_count = 0;

        //検出ウィンドウのスケール変化
        for (scale = MIN_SCALE; scale < MAX_SCALE; scale += STEP_SCALE){
            window_width = INIT_WINDOW_X * scale;
            window_height = INIT_WINDOW_Y * scale;

            //検出ウィンドウのラスタスキャン
            for (j = 0; j<imgSource->height - window_height; j += STEP_WIDTH){
                for (i = 0; i<imgSource->width - window_width; i += STEP_WIDTH){

                    //特徴量抽出
                    ob_IH.Getfeature(feature, i, j, window_width, window_height);

                    //検出ウィンドウが人であるかの識別
                    if (ob_CL.classifier(feature) == TRUE){
                        //検出ウィンドウの座標をストック
                        ob_MS.Voting(i + (int)(window_width * 0.5), j + (int)(window_height * 0.5), window_ture_count, scale);
                        window_ture_count++;
                    }
                }
            }
        }

        //MeanShiftによる検出ウィンドウの統合
        ob_MS.MeanShift();

        //Nearest Neighborによる検出ウィンドウの統合
        tcount = ob_MS.NearestNeighbor();

        //人がいると識別された領域を矩形で囲む
        for (l = 0; l < tcount; l++){
            //検出ウィンドウが統合された数がしきい値以下ならば人以外として判別
            if (ob_MS.win[l].count >= TH_HEAD_COUNT){
                //検出ウィンドウの縦幅と横幅を計算
                window_width = INIT_WINDOW_X * ob_MS.win[l].new_scale;
                window_height = INIT_WINDOW_Y * ob_MS.win[l].new_scale;

                //検出ウィンドウを矩形で囲む
                cvRectangle(imgResult, cvPoint(ob_MS.win[l].new_x - window_width * 0.5, ob_MS.win[l].new_y - window_height * 0.5), cvPoint(ob_MS.win[l].new_x + window_width * 0.5, ob_MS.win[l].new_y + window_height * 0.5), CV_RGB(0, 0, 255), 2, 8, 0);

            }
        }
        //人検出結果を保存と出力
        cvShowImage(winOriginal, imgResult);
        cvWaitKey(10);
        //1画面分の取り込み
        cvWriteFrame(VideoWriter, imgResult);

        // 確保したメモリを開放
        cvReleaseImage(&imgSource);
        cvReleaseImage(&imgResult);

        frame++;
    }

    // 確保したメモリを開放
    cvReleaseImage(&imgGray);
    cvReleaseVideoWriter(&VideoWriter);
    cvReleaseCapture(&capture);

    return 0;

}
コード
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • Chironian

    2015/12/22 19:37

    allocで出ている例外ですので、対象が広すぎて見当が付きません。もう少し絞り込んだ方がよいと思います。また、OSやコンパイラの情報も乗せるべきと思います。

    キャンセル

  • sh1208

    2015/12/23 10:21

    OSはwindows8.1 visual studio2013
    を使ってます。
    エラーの内容が見当がつかなすぎて、どこから絞ればいいのか途方にくれています。

    キャンセル

回答 4

+3

こんにちは。

情報の追加・修正の依頼をする

では書きにくいので、こちらから。

ご提示されているソースを全て精査し、問題がありそうな場所を指摘するって現実的ではないくらい長いソースです。せめて、エラーの場所が特定できていれば、その関連部を見ればよいので何とかなる時もあります。

エラーの内容が見当がつかなすぎて、どこから絞ればいいのか途方にくれています。

今回でているエラーはメモリ・アケーション周りと思われ、それはどこで発生しても可笑しくないエラーですので、我々も同じです。
つまり、どうにかするためにはsh1208さんのところで出ているエラーを再現しないと見当もつかない状態のままです。従って、再現するためにはsh1208さんが他のPCで同じ問題を再現させようとした場合に必要な情報が必要になります。

今回の場合、ざっくり下記情報が不足してます。(実際にやろうとしたら、他にも出てくるかも。)

①ソース・コード
opencvのヘッダは不要ですが、#include "..."でインクルードしているヘッダ群はopencvでは無いはずです。我々も持っていません。

②OSの情報
64bitですか、32bitですか?

③opecvのビルド方法
prebuild版を使われているようなら、ダウンロード元を提示頂くと確実です。
自前ビルドされたなら、そのオプションの与え方ですね。

④aviファイル
これを直接アップすることは難しいでしょう。特定のaviファイルで起きるわけでなく、いくつか試した全てで起きるのであれば、そのことを記載頂ければたぶん大丈夫かと。

で、ここまで書いときながら申し訳ないですが、ボランティアですので、私の方で再現トライできることの「約束」はできません。時間が取れない、再現トライする気力が湧かない、などなど様々な事情でトライしない可能性もあります。
その時はごめんなさい。でも、上記情報は私以外の方がトライする場合でも必要になる可能性が高い情報ですので、無駄にはならない可能性もありますから許して下さい。


【追記】
あっと、もう一点思い至りました。Visual Studioでステップ実行していけば、どこでエラーがでたか分かりませんか?


【追記】
うわっ、かなりの量のソースですね。ソース開示をお薦めしましたが、すいません、質問文に入りきれない量を上げて良いとは思えないです。ボランティアで成り立つシステムである以上出来ることには限界があると思います。

とはいえ、折角開示されたのでビルドできないかやってみましたが、できませんでした。
opencv_lib.hppはご指定場所のOpenCV 2.4.9に入っていないファイルのようです。
MeanShift.cppとClassifier.cppは#includeがないのでコンパイルエラーになります。
すいません、これ以上続けると他の方にも迷惑かけそうですし、私の方での再現トライはこの辺が限界です。

前回の追記で述べたようにステップ実行してエラー箇所を絞り込めませんか? それも無理なのでしたら、こんなに大きなソースの不具合解決は、ここでは難しいように感じます。
例えば、ここで対応してくれる人を探してみては如何でしょうか? 有償ですが、ビジネス・スキルさえあれば無償ポランティアより期待できると思います。

後、マルチ・ポストは結構嫌がられます。避けましょう。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/12/24 14:27

    ①ソースコード
    ヘッダファイルも回答の方に投稿しました。
    ②OSの情報
    64bitです。
    ③opecvのビルド方法
    http://opencv.org/downloads.html
    VERSION2.4.9の「OpenCV for Windows」をダウンロードしました。
    ④aviファイル
    いくつかファイルを試しましたが、同じエラーの内容でした。

    いろいろご教授いただき感謝しています。お時間があればで構わないので再現していただけるとこちらとしても助かります。
    また、並行して自分でもトライしていくつもりです。

    キャンセル

  • 2016/08/01 21:49

    https://github.com/opencv/opencv/blob/master/modules/core/src/alloc.cpp
    OpenCV内部のアサーションは fastFree 関数内で検出しているようです。ここからは推測にすぎませんが、(前方)バッファーオーバーランによるメモリ破壊か、そもそもOpenCVで動的確保されていないポインタをfreeしようとしたんだと思います。

    キャンセル

-1

MeanShift.h

//インクルードファイル指定
#include <opencv2/opencv.hpp>
//静的リンクライブラリの指定
#include <opencv2/opencv_lib.hpp>
#include <math.h>
#include <stdio.h>
#include <time.h>


#define PI                        3.14
#define RADIUS                    30.0//20.0    //検出ウィンドウの統合範囲
#define SCALE_RADIUS            0.5            //スケール空間統合範囲(バンド幅)


class CMeanShift
{

public:
    CMeanShift(void);
    ~CMeanShift(void);
    int Init(IplImage* img);
    int Voting(int w, int h, int count, double scale);
    int MeanShift();
    int NearestNeighbor();

    typedef struct{
        int old_x;
        int old_y;
        int new_x;
        int new_y;
        double old_scale;
        double new_scale;
        int count;
    }Window;
    struct Window win[4000];

private:
    int m_Width;
    int m_Height;
    int m_ImageSize;
    int bpp;
    int wStep;

    int m_count;
};


コード

MeanShift.cpp

CMeanShift::CMeanShift(void)
{
}

CMeanShift::~CMeanShift(void)
{
}


//初期化
int CMeanShift::Init(IplImage* img){
    m_Width = img->width;
    m_Height = img->height;
    m_ImageSize = m_Width*m_Height;
    wStep = img->widthStep;
    bpp = ((img->depth & 255) / 8) * img->nChannels;
    return 0;
}

//正規分布状に投票
int CMeanShift::Voting(int w, int h, int count, double scale){

    win[count].old_x = w;
    win[count].old_y = h;
    win[count].old_scale = scale;

    m_count = count;

    return 0;
}

int CMeanShift::MeanShift(){

    int i, j;
    double x, y, xi, yi, move_x, move_y, move_scale, Kernel, Kernel1, Kernel2;
    double scale, scalei;
    double sum_x = 0.0, sum_y = 0.0, sum_scale = 0.0, sum_w = 0.0;
    double radius;

    // 検出座標数だけ繰り返し
    for (i = 0; i<m_count; i++){
        x = win[i].old_x;
        y = win[i].old_y;
        scale = win[i].old_scale;

        while (1){
            //初期化
            sum_x = sum_y = sum_scale = sum_w = 0.0;

            //密度計算
            for (j = 0; j<m_count; j++){
                xi = win[j].old_x;
                yi = win[j].old_y;
                scalei = win[j].old_scale;

                //x-y空間のカーネル関数
                Kernel1 = -(((x - xi) * (x - xi) + (y - yi) * (y - yi)) / (RADIUS * RADIUS));
                Kernel1 = exp(Kernel1);

                //scale空間のカーネル関数
                Kernel2 = -(((scale - scalei) * (scale - scalei)) / (SCALE_RADIUS * SCALE_RADIUS));
                Kernel2 = exp(Kernel2);

                //カーネルの統合
                Kernel = Kernel1 * Kernel2;

                sum_x += xi * Kernel;
                sum_y += yi * Kernel;
                sum_scale += scalei * Kernel;
                sum_w += Kernel;
            }

            // 移動量の計算
            move_x = (sum_x / sum_w) - x;
            move_y = (sum_y / sum_w) - y;
            move_scale = (sum_scale / sum_w) - scale;
            x = x + move_x;
            y = y + move_y;
            scale = scale + move_scale;

            // 閾値以下に収束するまで
            if (move_x > -0.1 && move_x < 0.1 && move_y > -0.1 && move_y < 0.1 && move_scale > -SCALE_RADIUS && move_scale < SCALE_RADIUS){
                break;
            }
        }

        // Mean-Shift後位置保存
        win[i].new_x = int(x);
        win[i].new_y = int(y);
        win[i].new_scale = scale;
    }

    return 0;
}



int CMeanShift::NearestNeighbor(){
    int i, j;
    int count = 0;
    double d;
    double th = RADIUS;
    int flag;
    struct Window win2[4000];
    memset(win2, 0, sizeof(win2));
    int outcount;

    for (j = 0; j<m_count; j++){
        flag = 0;
        if (win[j].new_x != -100){
            win2[count].new_x = win[j].new_x;
            win2[count].new_y = win[j].new_y;
            win2[count].new_scale = win[j].new_scale;
            win2[count].count++;
            count++;
            flag = 1;

        }
        if (flag == 1){
            outcount = 0;
            for (i = j; i<m_count; i++){
                d = ((win[j].new_x - win[i].new_x) * (win[j].new_x - win[i].new_x) + (win[j].new_y - win[i].new_y) * (win[j].new_y - win[i].new_y));
                if (d < (th * th) && i != j){
                    win2[count - 1].count++;
                    win2[count - 1].new_x = (win2[count - 1].new_x + win[i].new_x) / 2.0;
                    win2[count - 1].new_y = (win2[count - 1].new_y + win[i].new_y) / 2.0;
                    win2[count - 1].new_scale = (win2[count - 1].new_scale + win[i].new_scale) / 2.0;
                    win[i].new_x = -100;
                    win[i].new_y = -100;
                    win[i].new_scale = -1.0;
                    win[i].count = 0;
                    outcount++;
                }
            }
        }
    }
    memcpy(win, win2, sizeof(win));

    return count;
}

コード

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

-1

IntegralHistogram.h

#define CELL_SIZE                8        //8*8pixel
#define BLOCK_SIZE                2        //2*2cell
#define PI                        3.14
#define LN_E                    1.0
#define SET_X_SIZE                64        //低解像度にしたときのXの大きさ
#define SET_Y_SIZE                128        //低解像度にしたときのYの大きさ
#define ORIENTATION                9
#define CW                        ( SET_X_SIZE / CELL_SIZE)    //セルの横幅
#define CH                        ( SET_Y_SIZE / CELL_SIZE)    //セルの縦幅
#define LUT_SIZE                511        //LUTのサイズ


class CIntegralHistogram
{
public:
    CIntegralHistogram(void);
    ~CIntegralHistogram(void);

    // 勾配方向,勾配強度のLUTを作成
    int CreateGradLUT();

    // 初期化
    int Init(IplImage* img);
    int InitIH();
    int ClearIH();

    // 各勾配の積分画像の作成
    int CreateIntegralHistogram(IplImage* img);
    int    CompIntegralImage(int image_w, int image_h);

    int Getfeature(double hog_feature[], int x, int y, int w_size, int h_size);

    // 正規化
    int Normalize(double hog_feature[]);

    // メモリーの解放
    int FreeImg();

private:
    // 各勾配方向の勾配強度
    double**  image[ORIENTATION];
    double cell_hist[CW][CH][ORIENTATION];

    int m_bpp;
    int m_wStep;
    int m_Width;
    int m_Height;
    double m_magnitudeLUT[LUT_SIZE][LUT_SIZE];
    int m_gradLUT[LUT_SIZE][LUT_SIZE];
};


コード

IntegralHistogram.cpp

#include <math.h>

// include: create
#include "IntegralHistogram.h"


CIntegralHistogram::CIntegralHistogram(void)
{
}

CIntegralHistogram::~CIntegralHistogram(void)
{
}

// 初期化
int CIntegralHistogram::Init(IplImage* img)
{
    m_wStep = img->widthStep;
    m_bpp = ((img->depth & 255) / 8) * img->nChannels;
    m_Width = img->width;
    m_Height = img->height;

    // 勾配方向,勾配強度のLUTを作成
    CreateGradLUT();

    // 各方向のIntegral Image(9方向分)の領域確保
    InitIH();

    return 0;
}

// 勾配方向,勾配強度のLUTを作成
int CIntegralHistogram::CreateGradLUT()
{
    int i, j;
    double x, y;

    double grad;

    // 勾配方向の算出
    for (j = 0; j < LUT_SIZE; j++){
        // 0から511を-255から255に変換
        y = j - 255;
        for (i = 0; i < LUT_SIZE; i++){
            // 0から511を-255から255に変換
            x = i - 255;
            m_magnitudeLUT[j][i] = sqrt(x*x + y*y);

            //勾配の大きさの計算
            grad = atan2(y, x);

            //ラジアンから角度へ変換
            grad = (grad * 180) / PI;
            grad -= 1.0;
            //マイナスは反転させる
            if (grad<0.0){
                grad += 360.0;
            }
            //0~360度を0~180度にする
            if (grad>180.0){
                grad = grad - 180.0;
            }
            //20度ずつにする.9分割
            m_gradLUT[j][i] = (int)grad / 20;
        }
    }

    return 0;
}

// 各方向のIntegral Image(9方向分)の領域確保
int CIntegralHistogram::InitIH()
{
    int i, j, k;

    // メモリの確保
    for (k = 0; k < ORIENTATION; k++){
        if ((image[k] = (double**)malloc(m_Height * sizeof(double*))) == NULL){
            fprintf(stderr, "Don't allocate memory.\n");
            exit(1);
        }

        for (j = 0; j < m_Height; j++){
            if ((image[k][j] = (double*)malloc(m_Width * sizeof(double))) == NULL){
                fprintf(stderr, "Don't allocate memory.\n");
                for (i = 0; i < j; i++){
                    free(image[k][i]);
                }
                free(image[k]);
                exit(1);
            }
        }
    }

    // 初期化
    for (k = 0; k < ORIENTATION; k++){
        for (j = 0; j < m_Height; j++){
            for (i = 0; i < m_Width; i++){
                image[k][j][i] = 0.0;
            }
        }
    }

    return 0;
}

//各方向のIntegral Image(9方向分)のメモリクリア
int CIntegralHistogram::ClearIH(){
    int i, j, k;

    // 初期化
    for (k = 0; k < ORIENTATION; k++){
        for (j = 0; j < m_Height; j++){
            for (i = 0; i < m_Width; i++){
                image[k][j][i] = 0.0;
            }
        }
    }

    return 0;
}

// 各方向のIntegral Imageを作成
int CIntegralHistogram::CreateIntegralHistogram(IplImage* img){
    int x, y;
    int xgrad, ygrad;

    int grad;            // 勾配方向

    int img_h = img->height;
    int img_w = img->width;

    int width_size;
    unsigned char* imgSource = (unsigned char*)img->imageData;

    // y軸方向の移動
    for (y = 0; y < img_h; y++){
        width_size = y * m_wStep;
        // x軸方向の移動
        for (x = 0; x < img_w; x++){
            //差分
            //difference integral
            if (x == 0){
                xgrad = imgSource[width_size + (x + 0)] - imgSource[width_size + (x + 1)];
            }
            else if (x == img_w - 1){
                xgrad = imgSource[width_size + (x - 1)] - imgSource[width_size + (x + 0)];
            }
            else{
                xgrad = imgSource[width_size + (x - 1)] - imgSource[width_size + (x + 1)];
            }
            if (y == 0){
                ygrad = imgSource[(y + 0)*m_wStep + x] - imgSource[(y + 1)*m_wStep + x];
            }
            else if (y == img_h - 1){
                ygrad = imgSource[(y - 1)*m_wStep + x] - imgSource[(y + 0)*m_wStep + x];
            }
            else{
                ygrad = imgSource[(y - 1)*m_wStep + x] - imgSource[(y + 1)*m_wStep + x];
            }

            xgrad = xgrad + 255;
            ygrad = ygrad + 255;

            // 勾配方向
            grad = m_gradLUT[ygrad][xgrad];

            // 勾配強度
            image[grad][y][x] = m_magnitudeLUT[ygrad][xgrad];
        }
    }

    // 各方向のIntegral Imageの算出
    CompIntegralImage(img_w, img_h);

    return 0;
}

// 各方向のIntegral Imageの算出
int CIntegralHistogram::CompIntegralImage(int image_w, int image_h){
    int  i, j, k;


    for (k = 0; k < ORIENTATION; k++){
        // y軸方向の加算
        for (j = 1; j < image_h; j++){
            for (i = 0; i < image_w; i++){
                image[k][j][i] = image[k][j - 1][i] + image[k][j][i];
            }
        }
        // x軸方向の加算
        for (j = 0; j < image_h; j++){
            for (i = 1; i < image_w; i++){
                image[k][j][i] = image[k][j][i - 1] + image[k][j][i];
            }
        }
    }

    return 0;
}

// 指定範囲内のintegral imageを算出
int CIntegralHistogram::Getfeature(double feature[], int x, int y, int w_size, int h_size){
    int p, q, k;
    int x1, x2, y1, y2;

    // 1セルが何ピクセルか算出
    int iw = w_size / CW;
    int ih = h_size / CH;

    //領域内の勾配方向ヒストグラムの作成
    for (q = 0; q < CH; q++){
        y1 = y + ih * q;
        y2 = y1 + ih - 1;

        for (p = 0; p < CW; p++){
            x1 = x + iw * p;
            x2 = x1 + iw - 1;

            if (x1 == 0){
                if (y1 == 0){
                    for (k = 0; k < ORIENTATION; k++){
                        cell_hist[p][q][k] = image[k][y2][x2];
                    }
                }
                else{
                    for (k = 0; k < ORIENTATION; k++){
                        cell_hist[p][q][k] = image[k][y2][x2] - image[k][y1 - 1][x2];
                    }
                }
            }
            else{
                if (y1 == 0){
                    for (k = 0; k < ORIENTATION; k++){
                        cell_hist[p][q][k] = image[k][y2][x2] - image[k][y2][x1 - 1];
                    }
                }
                else{
                    for (k = 0; k < ORIENTATION; k++){
                        cell_hist[p][q][k] = (image[k][y1 - 1][x1 - 1] + image[k][y2][x2]) - (image[k][y2][x1 - 1] + image[k][y1 - 1][x2]);
                    }
                }
            }
        }
    }

    // ヒストグラムの正規化と特徴量の取得
    Normalize(feature);

    return 0;
}

//正規化したHOG特徴量の取得
int CIntegralHistogram::Normalize(double feature[])
{
    int i, j, p, q, k;
    int c = 0;
    double sum_magnitude = 0.0;
    double e = LN_E;
    double div_regular;

    int box_w = CW - BLOCK_SIZE + 1;
    int box_h = CH - BLOCK_SIZE + 1;

    //y軸方向
    for (q = 0; q < box_h; q++){
        //x軸方向
        for (p = 0; p < box_w; p++){
            //y軸方向のセル内の移動
            for (j = 0; j < BLOCK_SIZE; j++){
                //x軸方向のセル内の移動
                for (i = 0; i < BLOCK_SIZE; i++){
                    for (k = 0; k < ORIENTATION; k++){
                        //正規化のためヒストグラムの総和の二乗を求める
                        sum_magnitude += cell_hist[p + i][q + j][k] * cell_hist[p + i][q + j][k];
                    }
                }
            }
            div_regular = 1.0 / sqrt(sum_magnitude + e);
            //y軸方向のセル内の移動
            for (j = 0; j < BLOCK_SIZE; j++){
                //x軸方向のセル内の移動
                for (i = 0; i < BLOCK_SIZE; i++){
                    //ヒストグラムの正規化
                    for (k = 0; k < ORIENTATION; k++){
                        // あらかじめ計算しておいた除数でかける
                        feature[c] = cell_hist[p + i][q + j][k] * div_regular;
                        //printf("%f\n", feature[c] );
                        c++;
                    }
                }
            }
            sum_magnitude = 0.0;
        }
    }

    return 0;
}

// メモリの解放
int CIntegralHistogram::FreeImg()
{
    int j, k;

    for (k = 0; k < ORIENTATION; k++){
        for (j = 0; j < m_Height; j++){
            free(image[k][j]);
        }
        free(image[k]);
    }

    return 0;
}
コード

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

-1

Common.h

#include <opencv2/opencv.hpp>
//静的リンクライブラリの指定
#include <opencv2/opencv_lib.hpp>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <windows.h>
#include <mmsystem.h>

//1個の検出ウィンドウから得られるHOG特徴量の個数
#define FEATURE                    3780

//検出ウィンドウのラスタスキャンを行う初期サイズ
#define INIT_WINDOW_X            30
#define INIT_WINDOW_Y            60

//検出ウィンドウの最小スケール
#define MIN_SCALE                1.0

//検出ウィンドウの最大スケール
#define MAX_SCALE                2.5

//検出ウィンドウのスケールの変化幅
#define STEP_SCALE                0.25

//検出ウィンドウをラスタスキャンする際のずらし幅
#define STEP_WIDTH                8

//検出ウィンドウの統合を行った際に,TH_HEAD_COUNTより少ない場合は人と識別しない
#define TH_HEAD_COUNT            3
コード


Classifier.h

#include "common.h"

//Real AdaBoostによって作成した検出器のフォルダ
#define CLASSIFIER_FILE_DIR        "C:\\DataSet\\InputData\\boost.dat"

//識別に使用する確率密度分布
#define LUT_DIR                    "C:\\DataSet\\InputData\\LUT\\"

#define POS                        1
#define NEG                        0
#define TRUE                    1
#define FALSE                    0
#define LEARNING_NUM            500                        //学習回数

#define EPSILON                    0.0000000001            //弱識別器の出力不可の回避
#define BIN                        64                        //確率密度分布(1次元ヒストグラム)のBIN数

#define TH                        3.0

//valが0以上の場合は1,それ以外は0
#define SIGN(val)    ((val == 0) ? 1 : (val < 0) ? 0 : 1)

class CClassifier
{
public:
    CClassifier(void);
    ~CClassifier(void);
    int init();
    int classifier(double feature[]);
    double Prediction(int learn, double feature[]);
    int ClassifierFileOpen();
    int LUTFileOpen();

private:
    //弱識別器として選択された特徴量の番号
    int            m_number[LEARNING_NUM];

    //弱識別器の確率密度分布
    double        m_WeakClassifierLUT[LEARNING_NUM][BIN];
};
コード

Classifier.cpp

CClassifier::CClassifier(void)
{
}

CClassifier::~CClassifier(void)
{
}

//初期化
int CClassifier::init(){

    //識別器と確率密度分布の読み込み
    ClassifierFileOpen();
    LUTFileOpen();

    return 0;
}

//検出器の読み込み
int CClassifier::ClassifierFileOpen(){
    int i;
    char fname[200];
    FILE* fp;

    sprintf(fname, "%s", CLASSIFIER_FILE_DIR);
    if ((fp = fopen(fname, "r")) == NULL){
        printf("File Open Error\n");
        exit(1);
    }
    for (i = 0; i<LEARNING_NUM; i++){
        fscanf(fp, "%d", &m_number[i]);
    }

    fclose(fp);
    return 0;
}


//確率密度分布読み込み
int CClassifier::LUTFileOpen(){
    int i, j;
    double pos, neg;
    char fname[200];
    int tmp;
    FILE* fp;

    for (j = 0; j<LEARNING_NUM; j++){

        sprintf(fname, "%s%d.dat", LUT_DIR, j);
        if ((fp = fopen(fname, "r")) == NULL){
            printf("File Open Error\n");
            exit(1);
        }
        for (i = 0; i<BIN; i++){
            fscanf(fp, "%d %lf %lf", &tmp, &pos, &neg);
            //ポジティブクラス,ネガティブクラスの確率密度分布から弱識別器の出力を予めLUTとして計算
            m_WeakClassifierLUT[j][i] = 0.5 * log((pos + EPSILON) / (neg + EPSILON));

        }
        fclose(fp);
    }

    return 0;
}

//弱識別器
double CClassifier::Prediction(int learn, double feature[]){

    int tmp;

    //1次元ヒストグラムで表される確率密度分布のどこのBINにくるかを計算
    tmp = (int)(feature[m_number[learn]] * BIN);
    if (tmp >= BIN){
        tmp = BIN - 1;
    }

    //LUTから弱識別器の読み込みを返す
    return m_WeakClassifierLUT[learn][tmp];
}

//強識別器
int CClassifier::classifier(double feature[]){

    int i;
    double p, q;
    double c;
    p = 0, q = 0;

    c = 0.0;
    //学習回数分だけ弱識別器による識別の繰り返し
    for (i = 0; i<LEARNING_NUM; i++){
        c += Prediction(i, feature);
    }

    //しきい値による判定
    if (c >= TH){
        return TRUE;
    }
    else{
        return FALSE;
    }
}
コード

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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

  • C++

    3957questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • OpenCV

    1321questions

    OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。