読者です 読者をやめる 読者になる 読者になる

のどあめ

ググってもなかなか出てこなかった情報を垂れ流すブログ。

OpenCV 3.0.0 beta で Dense samplingする

さて,先日の記事OpenCV 3.0.0 alpha で Dense samplingする - のどあめを書いたと思ったら,すぐにOpenCV 3.0.0 betaが出てしまいました.
(リリース予定くらいは確認すべきでした)

もちろん,研究室のうちのグループ(の私だけ)は,早速OpenCV 3.0.0 betaに切り替えました.しかし,先日実装したDenseSamplingのコードは,betaではコンパイルが通りません.
そこで,今回は先日の記事と同じようにOpenCV 3.0.0 betaでもDense Samplingの実装をしたいと思います.

Dense Samplingの実装(OpenCV 3.0.0 beta版)

前回のdetectImpl関数をdetectAndComputeに変更します.
detectなどはこの関数を内部で呼んでいるみたいです.
compute関数(DescriptorExtractor的な関数?)をoverrideしてassertを吐かせる方がいい気もしますが,今回は省略.

DenseFeatureDetector.h

#pragma once

#include <opencv2/opencv.hpp>
namespace cv {
	class DenseFeatureDetector : public cv::FeatureDetector {
	public:
		struct Param{
			int xStep = 4;
			int yStep = 4;

			float initFeatureScale = 1.0f;
			int scaleLevels = 1;
			float featureScaleMul = 1.2f;

			int imgBoundX = 0;
			int imgBoundY = 0;

			bool varyXyStepWithScale = true;
			bool varyImgBoundWithScale = false;
			Param(){}
		}param;

		DenseFeatureDetector(){}
		DenseFeatureDetector(const Param& p)
			:param(p)
		{
		}

		static cv::AlgorithmInfo& _info();
		virtual cv::AlgorithmInfo* info()const override;

		virtual void detectAndCompute( 
				cv::InputArray image, cv::InputArray mask,
				std::vector<cv::KeyPoint>& keypoints,
				cv::OutputArray descriptors,
				bool useProvidedKeypoints=false );

		static cv::Ptr<FeatureDetector> create(const Param& p=Param()){
			return cv::Ptr<FeatureDetector>(new DenseFeatureDetector(p));
		}
	};
}

DenseFeatureDetector.cpp

#include "DenseFeatureDetector.h"

namespace cv{
#define CV_INIT_ALGORITHM(classname, algname, memberinit) \
    static inline ::cv::Algorithm* create##classname##_hidden() \
    { \
        return new classname; \
    } \
    \
    static inline ::cv::Ptr< ::cv::Algorithm> create##classname##_ptr_hidden() \
    { \
        return ::cv::makePtr<classname>(); \
    } \
    \
    static inline ::cv::AlgorithmInfo& classname##_info() \
    { \
        static ::cv::AlgorithmInfo classname##_info_var(algname, create##classname##_hidden); \
        return classname##_info_var; \
    } \
    \
    static ::cv::AlgorithmInfo& classname##_info_auto = classname##_info(); \
    \
    ::cv::AlgorithmInfo* classname::info() const \
    { \
        static volatile bool initialized = false; \
        \
        if( !initialized ) \
        { \
            initialized = true; \
            classname obj; \
            memberinit; \
        } \
        return &classname##_info(); \
    }

	CV_INIT_ALGORITHM(DenseFeatureDetector, "Dense",);


	void DenseFeatureDetector::detectAndCompute( 
			cv::InputArray image, cv::InputArray mask,
			std::vector<cv::KeyPoint>& keypoints,
			cv::OutputArray descriptors,
			bool useProvidedKeypoints)
	{
		if (!useProvidedKeypoints) keypoints.clear();


		cv::Mat maskMat = mask.empty() ? cv::Mat(image.size(), CV_8UC1, cv::Scalar(255)) : mask.getMat();
		cv::Mat imageMat = image.getMat();

		int width = imageMat.cols;
		int height = imageMat.rows;

		int nowBoundX = param.imgBoundX;
		int nowBoundY = param.imgBoundY;

		int nowXStep = param.xStep;
		int nowYStep = param.yStep;

		float nowFeatureSize = param.initFeatureScale;

		for (int s = 0; s < param.scaleLevels; s++){
			for (int y = nowBoundY; y < height; y += nowYStep){
				unsigned char* maskline = maskMat.ptr<unsigned char>(y);

				for (int x = nowBoundX; x < width; x += nowYStep){
					if (maskline[x] > 128){
						cv::KeyPoint kp;
						kp.pt = cv::Point(x, y);
						kp.size = nowFeatureSize;
						kp.response = 100.0f;
						keypoints.push_back(kp);
					}
				}
			}

			if (param.varyImgBoundWithScale){
				nowBoundX *= param.featureScaleMul;
				nowBoundY *= param.featureScaleMul;
			}
			if (param.varyXyStepWithScale){
				nowXStep *= param.featureScaleMul;
				nowYStep *= param.featureScaleMul;
			}
			nowFeatureSize *= param.featureScaleMul;
		}
	}
}

基本的には関数名以外変える必要はありません.
これで,先日の記事のコードを動かすことで同様の結果が得られます.

今回のまとめ

  • 大きな仕様変更がなくてよかった.