OpenCV  切り貼りと連結

切り取りと結合(msvc2015,openvc3.1)
同じサイズの複数枚画像から指定部分を切り取り、それらを一枚の画像に合成します。


```Measure.cpp
//  : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include "stdafx.h"

#include <stdio.h>
#include <direct.h>
#include <iostream>
#include <fstream>
#include <list>
#include <vector>
#include <filesystem>


#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

#include "getopt.h"

using namespace std;


int main1(int argc, char* argv[]);
int main2(int argc, char* argv[]);
int main3(int argc, char* argv[]);

int usage(void)
{
	cout << "[usege] flmeasure <dirname>" << endl;
	cout << endl;
	cout << "OpenCV version: " << CV_VERSION << endl;
	return 1;
}

// メイン
int main(int argc, char* argv[])
{
	//return main1(argc, argv);
	//return main2(argc, argv);
	return main3(argc, argv);
}
//
//
// 
int main1(int argc, char* argv[])
{
	return main2(argc, argv);

	const int y = 1710;
	const int h = 80;
	double angle = 0.4;
	double scale = 1.0;


	cv::Mat src_img = cv::imread("C:\\MyData\\CUD099\\0706-4\\DSC00285.JPG");
	cv::namedWindow("Img", cv::WINDOW_AUTOSIZE);
	cv::namedWindow("Img2", cv::WINDOW_AUTOSIZE);
	// cv::namedWindow("Img3", cv::WINDOW_AUTOSIZE);
	cv::namedWindow("combined", cv::WINDOW_AUTOSIZE);
	//
	cv::Point2d center(0, y);		// 回転中心を指定
	const cv::Mat affine_matrix = cv::getRotationMatrix2D(center, angle, scale);
	//
	cv::warpAffine(src_img, src_img, affine_matrix, src_img.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar::all(255));

	cv::imshow("Img", src_img);

	cv::Mat img2(src_img, cv::Rect(0, y - h / 2, 3007, h));		// 切り取り
	cv::imshow("Img2", img2);

	cv::Mat combined(cv::Size(src_img.size().width, 1000), CV_8UC3);
	cv::Mat roi(combined, cv::Rect(0, 100, 3007, h));
	img2.copyTo(roi);
	cv::imshow("combined", combined);

	cv::waitKey(0);
	cv::destroyAllWindows();
	return 0;
}

int main2(int argc, char* argv[])
{
	cout << "FLMeasure 1.00 ((Fluid Level Measure))" << endl;

	// 1) 画像ファイルのあるディレクトリを決定する
	char defaultpath[_MAX_PATH] = "C:\\MyData\\CUD099\\0706-4";
	char pathname[_MAX_PATH];
	if (argc > 1) {
		strcpy_s(pathname, argv[1]);
	}
	else {
		strcpy_s(pathname, defaultpath);
	}

	// 2) ディレクトリ内のすべてのファイルのフルパスをlistに格納する。
	list<string> flist;
	std::tr2::sys::path p(pathname);

	for_each(std::tr2::sys::directory_iterator(p),
		std::tr2::sys::directory_iterator(),
		[&flist](const std::tr2::sys::path& p) {
		if (std::tr2::sys::is_regular_file(p)) {
			string s = p.string();
			flist.push_back(s);
		}
	});

	// 3) 画像を読み出し有効ならvectorに格納する。
	vector<cv::Mat> src_img;

	for (auto itn = flist.begin(); itn != flist.end(); itn++)
	{
		cv::Mat img = cv::imread(itn->data());
		if (img.empty()) {
			continue;
		}
		cout << itn->data() << endl;
		src_img.push_back(img);
	}
	if(src_img.empty()){
		return usage();
	}

	// 短冊状に切り出し、結合する。

	const int y = 1710;
	const int h = 40;
	double angle = 0.4;
	double scale = 1.0;

	// 結合結果保存用領域
	cv::Mat combined(cv::Size(src_img[0].size().width, src_img.size()*h), CV_8UC3);

	cv::Rect rot_rect;
	for (auto it = src_img.begin(); it != src_img.end(); it++)
	{

		//		cv::Point2d center(0, y);		// 回転中心を指定
		//		const cv::Mat affine_matrix = cv::getRotationMatrix2D(center, angle, scale);
		//		cv::warpAffine(it->data(), it->data(), affine_matrix, it->data().src_img.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar::all(255));

		cv::Mat img2((*it), cv::Rect(0, y - h / 2, 3007, h));		// 切り取り
		{


		}
		rot_rect.width = img2.cols;
		rot_rect.height = img2.rows;
		cv::Mat roi(combined, rot_rect);
		img2.copyTo(roi);

		rot_rect.y += img2.rows;

	}


	cv::imshow("combined", combined);
	string outdir = p.string() + "\\Result\\";
	_mkdir(outdir.c_str());
	string outfile = outdir +"combined.jpg";
	cv::imwrite(outfile, combined);

	cv::waitKey(0);

	return 0;
}



///////////////////////////////////////////////////////////////////////////////
// 
////////////////////////////////////////////////////////////////////////////////

int usage_main3()
{
	cout << "FLMesure <option> dirname " << endl;
	cout << " -Axxx : pointA.y 左上隅からの切り取り中心までの長さ" << endl;
	cout << " -Txxx : threshold (0 to 255" << endl;
	cout << endl;
	cout << "sample : flmesute -A1800 -T150 d:\0706-4" << endl;
	return 1;
}

int main3(int argc, char* argv[])
{
	cout << "FLMeasure 1.04 (Fluid Level Measure m3)" << endl;

	// パラメータ
	cv::Point ptA(0,1710);			// 左の点(切り出し画像中心)
	cv::Point ptB(0,1710);			// 右の点(切り出し画像中心)
	int hight = 40;					// 切り出し幅
	int threshold = 150;			// 閾値

								//
	// getoptを使用する。
	//	optarg			caseブロックの中で参照する。オプションに続く次のテキスト
	//	optind
	//	opterr			0でエラー表示抑制
	//	optopt			
	int optres;			
	while ((optres = getopt(argc, argv, "A:B:H:T:")) != -1) {
		switch (optres){
		case 'A':
			ptA.y = atoi(optarg);
			break;
		case 'B':break;
		case 'H':break;
		case 'T':
			threshold = atoi(optarg);
			break;
		default:
			return usage_main3();
		}
	}
	// 1) オプション以外の引数(ディレクトリ指定)
	char defaultpath[_MAX_PATH] = "C:\\MyData\\CUD099\\0706-4";
	char pathname[_MAX_PATH];
	strcpy_s(pathname, defaultpath);
	for(int i=optind; i<argc; i++){
		strcpy_s(pathname, argv[i]);
		break;
	}
	cout << "pointA.y= " << ptA.y << endl;
	cout << "threshold= " << threshold << endl;


	// 2) ディレクトリ内のすべてのファイルのフルパスをlistに格納する。
	list<string> flist;
	std::tr2::sys::path p(pathname);

	for_each(std::tr2::sys::directory_iterator(p),
		std::tr2::sys::directory_iterator(),
		[&flist](const std::tr2::sys::path& p) {
		if (std::tr2::sys::is_regular_file(p)) {
			string s = p.string();
			flist.push_back(s);
		}
	});
	// 


	// 3) 画像を読み出し有効ならvector<cv::Mat>に格納する。
	vector<cv::Mat> src_img;

	for (auto itn = flist.begin(); itn != flist.end(); itn++)
	{
		cv::Mat img = cv::imread(itn->data());
		if (img.empty()) {
			continue;
		}
		cout << itn->data() << endl;
		src_img.push_back(img);
	}
	if (src_img.empty()) {
		return usage();			// 画像なし
	}




	string outdir = p.string() + "\\Result\\";
	_mkdir(outdir.c_str());
	string outfile = outdir + "combined.jpg";
	string outcsv = outdir + "result.csv";

	ofstream ofs(outcsv);

	// 短冊状に切り出し、結合する。

	const int y = ptA.y;
	const int h = hight;
	double angle = 0.4;
	double scale = 1.0;

	// 結合結果保存用領域

	cv::Mat combined(cv::Size(src_img[0].size().width, src_img.size()*h), CV_8UC3);

	vector<cv::Mat> v1s;


	cv::Rect rot_rect;
	for (auto it = src_img.begin(); it != src_img.end(); it++)
	{

		//		cv::Point2d center(0, y);		// 回転中心を指定
		//		const cv::Mat affine_matrix = cv::getRotationMatrix2D(center, angle, scale);
		//		cv::warpAffine(it->data(), it->data(), affine_matrix, it->data().src_img.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar::all(255));

		cv::Mat img2((*it), cv::Rect(0, y - h / 2, src_img[0].size().width, h));		// 切り取り
		cv::Mat gray_img;
		cv::cvtColor(img2, gray_img, cv::COLOR_RGB2GRAY);			// グレイスケール
		cv::Mat v1;
		cv::reduce(gray_img, v1, 0, CV_REDUCE_AVG);					// 1行に縮小平均
		v1s.push_back(v1);
		{


		}
		rot_rect.width = img2.cols;
		rot_rect.height = img2.rows;
		cv::Mat roi(combined, rot_rect);
		img2.copyTo(roi);

		rot_rect.y += img2.rows;

	}

	cv::Mat iout;
	cv::vconcat(v1s, iout);				// 
	cv::Mat ioutt = iout.t();


	ofs << cv::format(ioutt, cv::Formatter::FMT_CSV);	// CSV形式で出力する。


	cv::imshow("iout", iout);


	//
	// ----------------------------------------------------------
	//
	ofs << endl << "結果" << " (閾値= " << threshold << " )" << endl;
	ofs << "No., 画素位置" << endl;
	for (int x = 0; x < ioutt.cols; x++) {
		ofs << x << ",";
		for (int y = 0; y < ioutt.rows; y++) {
			if (iout.at<unsigned char>(x, y) < threshold)
			{
				ofs << y << endl;
				break;
			}
		}
	}

//	for (int i = 0; i<iout.rows, i++){
//		for (int j = 0; j < iout.cols; j++) {
//			ofs << iout<unsigned char>(i, j) << ;
//
//		}
//	}


	// hconcat

#if 0
	cv::Mat mat = (*v1s.begin());
	for (auto it = mat.begin<unsigned char>(); it != mat.end<unsigned char>(); it++)
	{
		ofs << (int)(*it) << endl;
	}
#endif


	cv::imshow("combined", combined);
	cv::imwrite(outfile, combined);

	cv::waitKey(0);

	return 0;
}


```