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

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

ただいまの
回答率

88.64%

OpenCVのエラーを解決したい.

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 379

okomee

score 1

前提・実現したいこと

C++,OpenCVを用いてHOG特徴量の計算をするプログラムを作成したのですが,以下のようにエラーが出ます.

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

OpenCV: terminate handler is called! The last OpenCV error is:
OpenCV(3.4.10) Error: The function/feature is not implemented (Unsupported combination of buffer format (=5), and destination format (=4)) in cv::opt_AVX2::getLinearColumnFilter, file C:/build/3_4_winpack-build-win64-vc15/opencv/modules/imgproc/src/filter.simd.hpp, line 3021

該当のソースコード

#include"pch.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>

#include "opencv2/imgproc.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
#include "opencv2/imgcodecs.hpp"

using namespace std;
using namespace cv;

vector<Mat> caluculateIntegralHOG(const Mat& image);
void caluculateHOGInCell(Mat& hogCell, Rect roi, const vector<Mat>& integrals);
Mat getHOG(Point pt, const vector<Mat>integrals);




//ベクトルの次元はブロックの大きさ×ブロックの大きさ×勾配の方向数

//ビン(階級の個数)
#define N_BIN 9

//何度ずつに分けて投票するか(分解能)
#define THETA (180/N_BIN)


//セルの大きさ(ピクセル数)
#define CELL_SIZE 20

//ブロックの大きさ(セル数)※奇数
#define BLOCK_SIZE 3

//ブロックの大きさの半分
#define R (CELL_SIZE*(BLOCK_SIZE)*0.5)






int main(int argc, const char **argv) {

    FILE *fp = NULL;
    string sFilepath, sSaveFIlepath;
    errno_t err;
    string sMainFolder = "C:/food";

    Mat input_image;

    cout << "sFilepath=";
    cin >> sFilepath;

    input_image = imread(sFilepath, IMREAD_COLOR);


    Mat gray_image;

    cvtColor(input_image, gray_image, CV_BGR2GRAY);

    //積分画像の作成
    vector<Mat>integrals = caluculateIntegralHOG(gray_image);

    //ある点のHOG特徴量を求めるにはMat hist=getHOG(Point(x,y),integrals);とする.histはSize(81,1)CV_32F

    /* ****************************************

    以下表示のための処理

    ********************************************/

    //表示用の画像を用意(半分の輝度に)
    Mat image = input_image.clone();

    image *= 0.5;

    //格子点でHOG計算
    Mat meanHOGInBlock(Size(N_BIN, 1), CV_32F);

    for (int y = CELL_SIZE / 2; y < image.rows; y += CELL_SIZE) {
        for (int x = CELL_SIZE / 2; x < image.cols; x += CELL_SIZE) {

            //(x,y)でHOGを取得
            Mat hist = getHOG(Point(x, y), integrals);
            //ブロックがはみ出していたらcontinue
            if (hist.empty())continue;

            //ブロックごとに勾配ヒストグラム生成
            meanHOGInBlock = Scalar(0);

            for (int i = 0; i < N_BIN; i++) {
                for (int j = 0; j < BLOCK_SIZE*BLOCK_SIZE; j++) {

                    meanHOGInBlock.at<float>(0, i) += hist.at<float>(0, i + j * N_BIN);
                }
            }
            //L2ノルムで正規化(強い方向が強調される)
            normalize(meanHOGInBlock, meanHOGInBlock, 1, 0, CV_L2);

            //角度ごとに線を描画
            Point center(x, y);
            for (int i = 0; i < N_BIN; i++) {
                double theta = (i * THETA + 90.0)*CV_PI / 180;
                Point rd(CELL_SIZE*0.5*cos(theta), CELL_SIZE*0.5*sin(theta));
                Point rp = center - rd;
                Point lp = center - -rd;
                line(image, rp, lp, Scalar(255 * meanHOGInBlock.at<float>(0, i), 255, 255));
            }


        }
    }
    // 表示
    namedWindow("out", WINDOW_AUTOSIZE);
    imshow("out", image);
    waitKey(0);

    return 0;

}

//積分画像の作成
vector<Mat> caluculateIntegralHOG(const Mat& image) {

    //微分
    Mat xsobel, ysobel;
    Sobel(image, xsobel, CV_32S, 1, 0, 3);
    Sobel(image, ysobel, CV_32S, 0, 1, 3);

    //角度別の画像(9つ)を生成しておく
    vector<Mat>bins(N_BIN);
    for (int i = 0; i < N_BIN; i++) {
        bins[i] = Mat::zeros(image.size(), CV_32F);
    }

    //X,Y微分画像を勾配方向(angle)と強度(magnitude)に変換
    Mat Imag, Iang;

    cartToPolar(xsobel, ysobel, Imag, Iang, true);//true->degree[0,360),false->rad[0,2π)

    //勾配方向を[0,180)にする
    add(Iang, Scalar(180), Iang, Iang < 0);
    add(Iang, Scalar(-180), Iang, Iang >= 180);

    //勾配方向を[0,1,2.....8]にする準備
    Iang /= THETA;

    //勾配方向を強度で重みをつけて,角度別に投票する
    for (int y = 0; y < image.rows; y++) {
        for (int x = 0; x < image.cols; x++) {
            int ind = Iang.at<float>(y, x);
            bins[ind].at<float>(y, x) += Imag.at<float>(y, x);
        }
    }

    //角度別に積分画像を作成する
    vector<Mat>integrals(N_BIN);
    for (int i = 0; i < N_BIN; i++) {
        integral(bins[i], integrals[i]);
    }

    return integrals;

}


//HOG特徴量を計算する
//pt::ブロックの中心点
Mat getHOG(Point pt, const vector<Mat>integrals) {
    //ブロックが画像からはみ出していないか確認

    if (pt.x - R < 0 || pt.y - R < 0 || pt.x + R >= integrals[0].cols || pt.y + R >= integrals[0].rows) {
        return Mat();
    }
    //与点を中心としたブロックでセルごとに勾配ヒストグラムを求めて連結
    Mat hist(Size(N_BIN*BLOCK_SIZE*BLOCK_SIZE, 1), CV_32F);
    Point tl(0, pt.y - R);
    int c = 0;

    for (int i = 0; i < BLOCK_SIZE; i++) {
        tl.x = pt.x - R;
        for (int j = 0; i < BLOCK_SIZE; i++) {
            Mat temp = hist.colRange(c, c + N_BIN);
            caluculateHOGInCell(temp, Rect(tl, tl + Point(CELL_SIZE, CELL_SIZE)), integrals);
            tl.x += CELL_SIZE;
            c += N_BIN;
        }
        tl.y += CELL_SIZE;
    }

    //L2ノルムで正規化
    normalize(hist, hist, 1, 0, NORM_L2);
    return hist;


}
//セル内の勾配ヒストグラムを求める
void caluculateHOGInCell(Mat& hogCell, Rect roi, const vector<Mat>& integrals) {


    int x0 = roi.x;
    int y0 = roi.y;
    int x1 = x0 + roi.width;
    int y1 = y0 + roi.height;

    for (int i = 0; i < N_BIN; i++) {
        Mat integral = integrals[i];

        float a = integral.at<double>(y0, x0);
        float b = integral.at<double>(y1, x1);
        float c = integral.at<double>(y0, x1);
        float d = integral.at<double>(y1, x0);

        hogCell.at<float>(0, i) = (a + b) - (c + d);
    }
}

補足情報(FW/ツールのバージョンなど)

OpenCVのバージョンは3.4.10です.

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

caluculateIntegralHOG関数の

Sobel(image, xsobel, CV_32S, 1, 0, 3);
Sobel(image, ysobel, CV_32S, 0, 1, 3);


でエラーになっているようです。
デバッグしてみるとddepthCV_32Sがアサーションにかかっているようです。
当方の環境 (OpenCV 4.1.0) ではCV_32SCV_32Fに変更すると、エラーにならずに実行できました。
プログラムの内容を理解しているわけではないので、実行結果が正しいのかどうかは判断できないです。 

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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