diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2641667 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.mp4 diff --git a/README.md b/README.md new file mode 100644 index 0000000..80e4f27 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +Warp Cutter +=============== +映像中の矩形部位の四隅をトラッキングし,正面視点にワープ変形して表示する + +#### 開発環境 +- Visual C++ 2019 +- OpenCV 4.2.0 + +#### 使い方 +- 実行時引数として動画を指定(無指定時はカメラに接続) +- 開始後,初期フレームで静止した状態にて,対象矩形部位の四隅をクリック +- クリック順は 左上,左下,右上,右下 +- 'f' キーで再生・停止をトグル +- トラッキングがずれたら点をクリックして消去,再設定できる +- ただし上記の順番を維持する必要がある + +#### 履歴 +- 2020.3.9 ver1.0 + - 最初の実装 diff --git a/WarpCutter.sln b/WarpCutter.sln new file mode 100644 index 0000000..9141803 --- /dev/null +++ b/WarpCutter.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29806.167 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WarpCutter", "WarpCutter\WarpCutter.vcxproj", "{58D822AA-44D2-45EF-A591-603C78C67395}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {58D822AA-44D2-45EF-A591-603C78C67395}.Debug|x64.ActiveCfg = Debug|x64 + {58D822AA-44D2-45EF-A591-603C78C67395}.Debug|x64.Build.0 = Debug|x64 + {58D822AA-44D2-45EF-A591-603C78C67395}.Debug|x86.ActiveCfg = Debug|Win32 + {58D822AA-44D2-45EF-A591-603C78C67395}.Debug|x86.Build.0 = Debug|Win32 + {58D822AA-44D2-45EF-A591-603C78C67395}.Release|x64.ActiveCfg = Release|x64 + {58D822AA-44D2-45EF-A591-603C78C67395}.Release|x64.Build.0 = Release|x64 + {58D822AA-44D2-45EF-A591-603C78C67395}.Release|x86.ActiveCfg = Release|Win32 + {58D822AA-44D2-45EF-A591-603C78C67395}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5BA3AF72-0AA9-4C05-8EBA-3DE63965471E} + EndGlobalSection +EndGlobal diff --git a/WarpCutter/WarpCutter.cpp b/WarpCutter/WarpCutter.cpp new file mode 100644 index 0000000..5650474 --- /dev/null +++ b/WarpCutter/WarpCutter.cpp @@ -0,0 +1,168 @@ +#include "myOpenCV.h" +#include +#include + +using namespace cv; +using namespace std; + +static void help() +{ + // print a welcome message, and the OpenCV version + cout << "\nThis is Warp Cutter program,\n" + "Using OpenCV version " << CV_VERSION << endl; + cout << "\nIt uses camera by default, but you can provide a path to video as an argument.\n"; + cout << "Click four corner points to cut in order of TopLeft, BottomLeft, TopRight, BottomRight."; + cout << "\nHot keys: \n" + "\tESC - quit the program\n" + "\tf - toggle freeze-play movie\n" + "\tr - auto-initialize tracking\n" + "\tc - delete all the points\n" + "\tn - switch the \"night\" mode on/off\n" + "To add/remove a feature point click it\n" << endl; +} + +Point2f point; +bool addRemovePt = false; + +static void onMouse(int event, int x, int y, int /*flags*/, void* /*param*/) +{ + if (event == EVENT_LBUTTONDOWN) + { + point = Point2f((float)x, (float)y); + addRemovePt = true; + } +} + +int main(int argc, char** argv) +{ + VideoCapture cap; + TermCriteria termcrit(TermCriteria::COUNT | TermCriteria::EPS, 20, 0.03); + Size subPixWinSize(10, 10), winSize(31, 31); + + const int MAX_COUNT = 500; + bool needToInit = false; + bool nightMode = false; + bool freeze = true; + + help(); + cv::CommandLineParser parser(argc, argv, "{@input|0|}"); + string input = parser.get("@input"); + + if (input.size() == 1 && isdigit(input[0])) + cap.open(input[0] - '0'); + else + cap.open(input); + + if (!cap.isOpened()) + { + cout << "Could not initialize capturing...\n"; + return 0; + } + + const String WIN_MAIN = "Movie Tracking"; + const String WIN_WARP = "Warped image"; + namedWindow(WIN_MAIN, WINDOW_NORMAL); + namedWindow(WIN_WARP, WINDOW_AUTOSIZE); + setMouseCallback(WIN_MAIN, onMouse, 0); + + Mat gray, prevGray, image, frame; + vector points[2]; + Size2f warpSize = Size2f(640.F, 480.F); + vector target; + target.push_back(Point2f(0, 0)); + target.push_back(Point2f(0, warpSize.height)); + target.push_back(Point2f(warpSize.width, 0)); + target.push_back(Point2f(warpSize.width, warpSize.height)); + Mat dst(warpSize, CV_8UC3, CV_RGB(50, 50, 50)); + + for (;;) + { + if (frame.empty() || !freeze) cap >> frame; + if (frame.empty()) + break; + + frame.copyTo(image); + cvtColor(image, gray, COLOR_BGR2GRAY); + + if (nightMode) + image = Scalar::all(0); + + if (needToInit) + { + // automatic initialization + goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 3, 0, 0.04); + cornerSubPix(gray, points[1], subPixWinSize, Size(-1, -1), termcrit); + addRemovePt = false; + } else if (!points[0].empty()) + { + vector status; + vector err; + if (prevGray.empty()) + gray.copyTo(prevGray); + calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize, + 3, termcrit, 0, 0.001); + size_t i, k; + for (i = k = 0; i < points[1].size(); i++) + { + if (addRemovePt) + { + if (norm(point - points[1][i]) <= 5) + { + addRemovePt = false; + continue; + } + } + + if (!status[i]) + continue; + + points[1][k++] = points[1][i]; + circle(image, points[1][i], 3, Scalar(0, 255, 0), -1, 8); + } + points[1].resize(k); + } + + if (addRemovePt && points[1].size() < (size_t)MAX_COUNT) + { + vector tmp; + tmp.push_back(point); + cornerSubPix(gray, tmp, winSize, Size(-1, -1), termcrit); + points[1].push_back(tmp[0]); + addRemovePt = false; + } + + if (points[1].size() == 4) { + Mat homography_matrix = getPerspectiveTransform(points[1], target); + warpPerspective(frame, dst, homography_matrix, dst.size()); + imshow(WIN_WARP, dst); + } + + needToInit = false; + imshow(WIN_MAIN, image); + + char c = (char)waitKey(10); + if (c == 27) + break; + switch (c) + { + case 'r': + needToInit = true; + break; + case 'f': + freeze = !freeze; + break; + case 'c': + points[0].clear(); + points[1].clear(); + break; + case 'n': + nightMode = !nightMode; + break; + } + + std::swap(points[1], points[0]); + cv::swap(prevGray, gray); + } + + return 0; +} \ No newline at end of file diff --git a/WarpCutter/WarpCutter.vcxproj b/WarpCutter/WarpCutter.vcxproj new file mode 100644 index 0000000..779aabf --- /dev/null +++ b/WarpCutter/WarpCutter.vcxproj @@ -0,0 +1,153 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {58D822AA-44D2-45EF-A591-603C78C67395} + WarpCutter + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/WarpCutter/WarpCutter.vcxproj.filters b/WarpCutter/WarpCutter.vcxproj.filters new file mode 100644 index 0000000..9a6a841 --- /dev/null +++ b/WarpCutter/WarpCutter.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + ヘッダー ファイル + + + + + ソース ファイル + + + \ No newline at end of file diff --git a/WarpCutter/myOpenCV.h b/WarpCutter/myOpenCV.h new file mode 100644 index 0000000..5fa984e --- /dev/null +++ b/WarpCutter/myOpenCV.h @@ -0,0 +1,102 @@ + +// OpenCV 3�n, 4�n ���ʃw�b�_�[�t�@�C�� +// T.Nakaguchi, CFME, Chiba Univ., 2019 + +#pragma once + +// �w�b�_�[�t�@�C�� +#pragma warning(disable: 4819) +#include +#pragma warning(default: 4819) + +// �o�[�W�����擾 +#define CV_VERSION_STR CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION) + +// �r���h���[�h +#ifdef _DEBUG +#define CV_EXT_STR "d.lib" +#else +#define CV_EXT_STR ".lib" +#endif + +// ���C�u�����̃����N�i�s�v�ȕ��̓R�����g�A�E�g�j +#define PRE_COMPILE 0 // �C���X�g�[���łȂ� 1 �•ʃ��C�u�����g�p���� 0 +#define PREHEAD "opencv_" + +#if PRE_COMPILE +// OpenCV3 �C���X�g�[���� +#pragma comment(lib, PREHEAD "world" CV_VERSION_STR CV_EXT_STR) // �S�� +#pragma comment(lib, PREHEAD "ts" CV_VERSION_STR CV_EXT_STR) // �f���֘A + +#else +// �•ʂ̃��C�u�����w�� �iCmake��Static�Ŏg�p���Ȃǁj +// ��{���W���[�� +#pragma comment(lib, PREHEAD "core" CV_VERSION_STR CV_EXT_STR) // Core functionality +#pragma comment(lib, PREHEAD "imgproc" CV_VERSION_STR CV_EXT_STR) // Image processing +#pragma comment(lib, PREHEAD "imgcodecs" CV_VERSION_STR CV_EXT_STR) // Image file reading and writing +#pragma comment(lib, PREHEAD "videoio" CV_VERSION_STR CV_EXT_STR) // Video I/O +#pragma comment(lib, PREHEAD "highgui" CV_VERSION_STR CV_EXT_STR) // High-level GUI +#pragma comment(lib, PREHEAD "video" CV_VERSION_STR CV_EXT_STR) // Video Analysis +//#pragma comment(lib, PREHEAD "calib3d" CV_VERSION_STR CV_EXT_STR) // Camera Calibration and 3D Reconstruction +//#pragma comment(lib, PREHEAD "features2d" CV_VERSION_STR CV_EXT_STR) // 2D Features Framework +//#pragma comment(lib, PREHEAD "objdetect" CV_VERSION_STR CV_EXT_STR) // Object Detection +//#pragma comment(lib, PREHEAD "dnn" CV_VERSION_STR CV_EXT_STR) // Deep Neural Network module +//#pragma comment(lib, PREHEAD "ml" CV_VERSION_STR CV_EXT_STR) // Machine Learning +//#pragma comment(lib, PREHEAD "flann" CV_VERSION_STR CV_EXT_STR) // Clustering and Search in Multi-Dimensional Spaces +//#pragma comment(lib, PREHEAD "photo" CV_VERSION_STR CV_EXT_STR) // Computational Photography +//#pragma comment(lib, PREHEAD "stitching" CV_VERSION_STR CV_EXT_STR) // Images stitching +//#pragma comment(lib, PREHEAD "cudaarithm" CV_VERSION_STR CV_EXT_STR) // CUDA Operations on Matrices +//#pragma comment(lib, PREHEAD "cudabgsegm" CV_VERSION_STR CV_EXT_STR) // CUDA Background Segmentation +//#pragma comment(lib, PREHEAD "cudacodec" CV_VERSION_STR CV_EXT_STR) // CUDA Video Encoding/Decoding +//#pragma comment(lib, PREHEAD "cudafeatures2d" CV_VERSION_STR CV_EXT_STR) // CUDA Feature Detection and Description +//#pragma comment(lib, PREHEAD "cudafilters" CV_VERSION_STR CV_EXT_STR) // CUDA Image Filtering +//#pragma comment(lib, PREHEAD "cudaimgproc" CV_VERSION_STR CV_EXT_STR) // CUDA Image Processing +//#pragma comment(lib, PREHEAD "cudalegacy" CV_VERSION_STR CV_EXT_STR) // CUDA Legacy support +//#pragma comment(lib, PREHEAD "cudaobjdetect" CV_VERSION_STR CV_EXT_STR) // CUDA Object Detection +//#pragma comment(lib, PREHEAD "cudaoptflow" CV_VERSION_STR CV_EXT_STR) // CUDA Optical Flow +//#pragma comment(lib, PREHEAD "cudastereo" CV_VERSION_STR CV_EXT_STR) // CUDA Stereo Correspondence +//#pragma comment(lib, PREHEAD "cudawarping" CV_VERSION_STR CV_EXT_STR) // CUDA Image Warping +//#pragma comment(lib, PREHEAD "cudev" CV_VERSION_STR CV_EXT_STR) // CUDA Device layer +//#pragma comment(lib, PREHEAD "shape" CV_VERSION_STR CV_EXT_STR) // Shape Distance and Matching +//#pragma comment(lib, PREHEAD "superres" CV_VERSION_STR CV_EXT_STR) // Super Resolution +//#pragma comment(lib, PREHEAD "videostab" CV_VERSION_STR CV_EXT_STR) // Video Stabilization +//#pragma comment(lib, PREHEAD "viz" CV_VERSION_STR CV_EXT_STR) // 3D Visualizer + +// �g�����W���[�� +//#pragma comment(lib, PREHEAD "aruco" CV_VERSION_STR CV_EXT_STR) // ArUco Marker Detection +//#pragma comment(lib, PREHEAD "bgsegm" CV_VERSION_STR CV_EXT_STR) // Improved Background-Foreground Segmentation Methods +//#pragma comment(lib, PREHEAD "bioinspired" CV_VERSION_STR CV_EXT_STR) // Biologically inspired vision models and derivated tools +//#pragma comment(lib, PREHEAD "ccalib" CV_VERSION_STR CV_EXT_STR) // Custom Calibration Pattern for 3D reconstruction +//#pragma comment(lib, PREHEAD "cnn_3dobj" CV_VERSION_STR CV_EXT_STR) // 3D object recognition and pose estimation API +//#pragma comment(lib, PREHEAD "cvv" CV_VERSION_STR CV_EXT_STR) // GUI for Interactive Visual Debugging of Computer Vision Programs +//#pragma comment(lib, PREHEAD "datasets" CV_VERSION_STR CV_EXT_STR) // Framework for working with different datasets +//#pragma comment(lib, PREHEAD "dnn_objdetect" CV_VERSION_STR CV_EXT_STR) // DNN used for object detection +//#pragma comment(lib, PREHEAD "dpm" CV_VERSION_STR CV_EXT_STR) // Deformable Part-based Models +//#pragma comment(lib, PREHEAD "face" CV_VERSION_STR CV_EXT_STR) // Face Analysis +//#pragma comment(lib, PREHEAD "freetype" CV_VERSION_STR CV_EXT_STR) // Drawing UTF-8 strings with freetype/harfbuzz +//#pragma comment(lib, PREHEAD "fuzzy" CV_VERSION_STR CV_EXT_STR) // Image processing based on fuzzy mathematics +//#pragma comment(lib, PREHEAD "hdf" CV_VERSION_STR CV_EXT_STR) // Hierarchical Data Format I/O routines +//#pragma comment(lib, PREHEAD "hfs" CV_VERSION_STR CV_EXT_STR) // Hierarchical Feature Selection for Efficient Image Segmentation +//#pragma comment(lib, PREHEAD "img_hash" CV_VERSION_STR CV_EXT_STR) // The module brings implementations of different image hashing algorithms. +//#pragma comment(lib, PREHEAD "line_descriptor" CV_VERSION_STR CV_EXT_STR) // Binary descriptors for lines extracted from an image +//#pragma comment(lib, PREHEAD "matlab" CV_VERSION_STR CV_EXT_STR) // MATLAB Bridge +//#pragma comment(lib, PREHEAD "optflow" CV_VERSION_STR CV_EXT_STR) // Optical Flow Algorithms +//#pragma comment(lib, PREHEAD "ovis" CV_VERSION_STR CV_EXT_STR) // OGRE 3D Visualiser +//#pragma comment(lib, PREHEAD "phase_unwrapping" CV_VERSION_STR CV_EXT_STR) // Phase Unwrapping API +//#pragma comment(lib, PREHEAD "plot" CV_VERSION_STR CV_EXT_STR) // Plot function for Mat data +//#pragma comment(lib, PREHEAD "reg" CV_VERSION_STR CV_EXT_STR) // Image Registration +//#pragma comment(lib, PREHEAD "rgbd" CV_VERSION_STR CV_EXT_STR) // RGB-Depth Processing +//#pragma comment(lib, PREHEAD "saliency" CV_VERSION_STR CV_EXT_STR) // Saliency API +//#pragma comment(lib, PREHEAD "sfm" CV_VERSION_STR CV_EXT_STR) // Structure From Motion +//#pragma comment(lib, PREHEAD "stereo" CV_VERSION_STR CV_EXT_STR) // Stereo Correspondance Algorithms +//#pragma comment(lib, PREHEAD "structured_light" CV_VERSION_STR CV_EXT_STR) // Structured Light API +//#pragma comment(lib, PREHEAD "surface_matching" CV_VERSION_STR CV_EXT_STR) // Surface Matching +//#pragma comment(lib, PREHEAD "text" CV_VERSION_STR CV_EXT_STR) // Scene Text Detection and Recognition +//#pragma comment(lib, PREHEAD "tracking" CV_VERSION_STR CV_EXT_STR) // Tracking API +//#pragma comment(lib, PREHEAD "xfeatures2d" CV_VERSION_STR CV_EXT_STR) // Extra 2D Features Framework +//#pragma comment(lib, PREHEAD "ximgproc" CV_VERSION_STR CV_EXT_STR) // Extended Image Processing +//#pragma comment(lib, PREHEAD "xobjdetect" CV_VERSION_STR CV_EXT_STR) // Extended object detection +//#pragma comment(lib, PREHEAD "xphoto" CV_VERSION_STR CV_EXT_STR) // Additional photo processing algorithms +#endif + +using namespace cv; diff --git a/WarpCutter/opencv420gst.props b/WarpCutter/opencv420gst.props new file mode 100644 index 0000000..97297f8 --- /dev/null +++ b/WarpCutter/opencv420gst.props @@ -0,0 +1,15 @@ + + + + + + D:\SDK\OpenCV4.2.0_GST\include;$(IncludePath) + D:\SDK\OpenCV4.2.0_GST\x64\vc16\lib;$(LibraryPath) + + + D:\SDK\OpenCV4.2.0_GST\include;$(IncludePath) + D:\SDK\OpenCV4.2.0_GST\x86\vc16\lib\lib;$(LibraryPath) + + + +