1. ホーム
  2. C++

C++-サンプリング関数 GridSampling (要サンプリング高速化)

2022-02-09 20:34:15

著者 スティーブン・ザイ ティエンバオ
著作権について 著作権は著者に帰属します。商業的な複製は著者に、非商業的な複製は出典を明記してください。

シナリオの要件

       サンプリングは、大量のデータ計算を行う際によく使われる最適化手法で、合理的なサンプリング手法を用いれば、計算を数十倍、数百倍に高速化することができます。例えば、1000*1000の画像データを100回反復して計算しなければならない場合、サンプリング法を用いて100*100の画像データを抽出して解析すれば、少なくとも100倍は速くなり、無駄な計算が大幅に減るので、プログラムの速度も上がります。私は通常、表面フィットに使用する方法は、迅速にフィット係数を計算するだけでなく、一般的に反復計算に使用されます。しかし、それは合理的なサンプリング間隔が重要であることに注意する必要があり、単に速度の追求ではなく、サンプリング速度も有効データの減少を意味し、結果は一定の影響であり、合理的な設計は、この影響を無視することは可能です。

       さっそくですが、具体的な実装関数とテストコードを紹介します。

機能コード

/**
 * @brief GridSampling sets the position point to be sampled
 * @param size The size of the range to resample
 * @param rowinterval row interval
 * @param colinterval Column interval
 * @return resample mask
 */
cv::Mat GridSampling(const cv::Size& size, int rowinterval, int colinterval) 
{
	cv::Mat dst(size, CV_8UC1, cv::Scalar(0));
	// Set the position point for sampling
	int Row = dst.rows;
	int Col = dst.cols;
	for (int row = 0; row < Row; row += rowinterval) {
		for (int col = 0; col < Col; col += colinterval) {
			dst.at<uchar>(row, col) = 255;
		}
	}
	return dst;
}

C++テストコード

#include <iostream>
#include <opencv.hpp>
using namespace std;
using namespace cv;
cv::Mat GridSampling(const cv::Size& size, int rowinterval, int colinterval);
int main()
{
	// Generate a random matrix
	cv::Mat src(100,100,CV_32FC1);
	for (int i = 0; i < 100; ++i)
	{
		for (int j = 0; j < 100; ++j)
		{
			src.at<float>(i, j) = rand() % 255;
		}
	}

	// Create the mask mask
	cv::Mat mask = cv::Mat::zeros(src.size(), CV_8UC1);
	cv::circle(mask, cv::Point(50, 50), 40, 255, -1);

	// Create the sample area
	int sampInterval = 2; // sample interval of 2
	cv::Mat samp = GridSampling(src.size(), sampInterval, sampInterval);
	cv::Mat samp_mask = samp.clone();
	samp_mask.setTo(0, ~mask);

	// Place the data from the sample area in sampling to store it for subsequent computation
	std::vector<cv::Point> samplingidx_roi;
	cv::findNonZero(samp_mask, samplingidx_roi);
	int len = (int)samplingidx_roi.size();
	cv::Mat sampling(len, 1, CV_32FC1, 0.0f);
	auto tmp = samplingidx_roi.begin();
	for (int i = 0; i < len; ++i, ++tmp) {
		int x = tmp->x;
		int y = tmp->y;
		sampling.ptr<float>(i)[0] = src.ptr<float>(y)[x];
	}

	system("pause");
	return 0;
}

/**
 * @brief GridSampling sets the location of the sampled points.
 * @param size The size of the range to resample.
 * @param rowinterval row interval
 * @param colinterval Column interval
 * @return resample mask
 */
cv::Mat GridSampling(const cv::Size& size, int rowinterval, int colinterval) 
{
	cv::Mat dst(size, CV_8UC1, cv::Scalar(0));
	// Set the position point for sampling
	int Row = dst.rows;
	int Col = dst.cols;
	for (int row = 0; row < Row; row += rowinterval) {
		for (int col = 0; col < Col; col += colinterval) {
			dst.at<uchar>(row, col) = 255;
		}
	}
	return dst;
}

テスト結果

図1 領域作成例
図2 領域マスク処理の例
図3 サンプリングデータ

       テストケースでは、100*100のデータマトリックスをランダムに生成し、サンプリング機能でサンプリング領域を作成し、マスクを適用し、計算するサンプリング点に対応するデータをサンプリングマトリックスに配置し、1257をサンプリング点数とし、いくつかのマトリックス計算を行うことで様々な機能を実現することができます。

       もし、この機能を改善できる点があれば、ぜひご指摘ください。一緒に進歩していきましょう。

       もしこの記事が役に立ったなら、いいね!で教えてくれたら嬉しいな~ Go!