Cv2_video.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. using OpenCvSharp.Internal;
  2. using OpenCvSharp.Internal.Vectors;
  3. namespace OpenCvSharp;
  4. // ReSharper disable InconsistentNaming
  5. static partial class Cv2
  6. {
  7. /// <summary>
  8. /// Finds an object center, size, and orientation.
  9. /// </summary>
  10. /// <param name="probImage">Back projection of the object histogram. </param>
  11. /// <param name="window">Initial search window.</param>
  12. /// <param name="criteria">Stop criteria for the underlying MeanShift() .</param>
  13. /// <returns></returns>
  14. public static RotatedRect CamShift(
  15. InputArray probImage, ref Rect window, TermCriteria criteria)
  16. {
  17. if (probImage is null)
  18. throw new ArgumentNullException(nameof(probImage));
  19. probImage.ThrowIfDisposed();
  20. NativeMethods.HandleException(
  21. NativeMethods.video_CamShift(
  22. probImage.CvPtr, ref window, criteria, out var ret));
  23. GC.KeepAlive(probImage);
  24. return ret;
  25. }
  26. /// <summary>
  27. /// Finds an object on a back projection image.
  28. /// </summary>
  29. /// <param name="probImage">Back projection of the object histogram.</param>
  30. /// <param name="window">Initial search window.</param>
  31. /// <param name="criteria">Stop criteria for the iterative search algorithm.</param>
  32. /// <returns>Number of iterations CAMSHIFT took to converge.</returns>
  33. public static int MeanShift(
  34. InputArray probImage, ref Rect window, TermCriteria criteria)
  35. {
  36. if (probImage is null)
  37. throw new ArgumentNullException(nameof(probImage));
  38. probImage.ThrowIfDisposed();
  39. NativeMethods.HandleException(
  40. NativeMethods.video_meanShift(
  41. probImage.CvPtr, ref window, criteria, out var ret));
  42. GC.KeepAlive(probImage);
  43. return ret;
  44. }
  45. /// <summary>
  46. /// Constructs a pyramid which can be used as input for calcOpticalFlowPyrLK
  47. /// </summary>
  48. /// <param name="img">8-bit input image.</param>
  49. /// <param name="pyramid">output pyramid.</param>
  50. /// <param name="winSize">window size of optical flow algorithm.
  51. /// Must be not less than winSize argument of calcOpticalFlowPyrLK().
  52. /// It is needed to calculate required padding for pyramid levels.</param>
  53. /// <param name="maxLevel">0-based maximal pyramid level number.</param>
  54. /// <param name="withDerivatives">set to precompute gradients for the every pyramid level.
  55. /// If pyramid is constructed without the gradients then calcOpticalFlowPyrLK() will
  56. /// calculate them internally.</param>
  57. /// <param name="pyrBorder">the border mode for pyramid layers.</param>
  58. /// <param name="derivBorder">the border mode for gradients.</param>
  59. /// <param name="tryReuseInputImage">put ROI of input image into the pyramid if possible.
  60. /// You can pass false to force data copying.</param>
  61. /// <returns>number of levels in constructed pyramid. Can be less than maxLevel.</returns>
  62. public static int BuildOpticalFlowPyramid(
  63. InputArray img, OutputArray pyramid,
  64. Size winSize, int maxLevel,
  65. bool withDerivatives = true,
  66. BorderTypes pyrBorder = BorderTypes.Reflect101,
  67. BorderTypes derivBorder = BorderTypes.Constant,
  68. bool tryReuseInputImage = true)
  69. {
  70. if (img is null)
  71. throw new ArgumentNullException(nameof(img));
  72. if (pyramid is null)
  73. throw new ArgumentNullException(nameof(pyramid));
  74. img.ThrowIfDisposed();
  75. pyramid.ThrowIfNotReady();
  76. NativeMethods.HandleException(
  77. NativeMethods.video_buildOpticalFlowPyramid1(
  78. img.CvPtr, pyramid.CvPtr, winSize, maxLevel, withDerivatives ? 1 : 0,
  79. (int) pyrBorder, (int) derivBorder, tryReuseInputImage ? 1 : 0, out var ret));
  80. pyramid.Fix();
  81. GC.KeepAlive(img);
  82. return ret;
  83. }
  84. /// <summary>
  85. /// Constructs a pyramid which can be used as input for calcOpticalFlowPyrLK
  86. /// </summary>
  87. /// <param name="img">8-bit input image.</param>
  88. /// <param name="pyramid">output pyramid.</param>
  89. /// <param name="winSize">window size of optical flow algorithm.
  90. /// Must be not less than winSize argument of calcOpticalFlowPyrLK().
  91. /// It is needed to calculate required padding for pyramid levels.</param>
  92. /// <param name="maxLevel">0-based maximal pyramid level number.</param>
  93. /// <param name="withDerivatives">set to precompute gradients for the every pyramid level.
  94. /// If pyramid is constructed without the gradients then calcOpticalFlowPyrLK() will
  95. /// calculate them internally.</param>
  96. /// <param name="pyrBorder">the border mode for pyramid layers.</param>
  97. /// <param name="derivBorder">the border mode for gradients.</param>
  98. /// <param name="tryReuseInputImage">put ROI of input image into the pyramid if possible.
  99. /// You can pass false to force data copying.</param>
  100. /// <returns>number of levels in constructed pyramid. Can be less than maxLevel.</returns>
  101. public static int BuildOpticalFlowPyramid(
  102. InputArray img, out Mat[] pyramid,
  103. Size winSize, int maxLevel,
  104. bool withDerivatives = true,
  105. BorderTypes pyrBorder = BorderTypes.Reflect101,
  106. BorderTypes derivBorder = BorderTypes.Constant,
  107. bool tryReuseInputImage = true)
  108. {
  109. if (img is null)
  110. throw new ArgumentNullException(nameof(img));
  111. img.ThrowIfDisposed();
  112. using var pyramidVec = new VectorOfMat();
  113. NativeMethods.HandleException(
  114. NativeMethods.video_buildOpticalFlowPyramid2(
  115. img.CvPtr, pyramidVec.CvPtr, winSize, maxLevel, withDerivatives ? 1 : 0,
  116. (int) pyrBorder, (int) derivBorder, tryReuseInputImage ? 1 : 0, out var ret));
  117. GC.KeepAlive(img);
  118. pyramid = pyramidVec.ToArray();
  119. return ret;
  120. }
  121. /// <summary>
  122. /// computes sparse optical flow using multi-scale Lucas-Kanade algorithm
  123. /// </summary>
  124. /// <param name="prevImg"></param>
  125. /// <param name="nextImg"></param>
  126. /// <param name="prevPts"></param>
  127. /// <param name="nextPts"></param>
  128. /// <param name="status"></param>
  129. /// <param name="err"></param>
  130. /// <param name="winSize"></param>
  131. /// <param name="maxLevel"></param>
  132. /// <param name="criteria"></param>
  133. /// <param name="flags"></param>
  134. /// <param name="minEigThreshold"></param>
  135. public static void CalcOpticalFlowPyrLK(
  136. InputArray prevImg, InputArray nextImg,
  137. InputArray prevPts, InputOutputArray nextPts,
  138. OutputArray status, OutputArray err,
  139. Size? winSize = null,
  140. int maxLevel = 3,
  141. TermCriteria? criteria = null,
  142. OpticalFlowFlags flags = OpticalFlowFlags.None,
  143. double minEigThreshold = 1e-4)
  144. {
  145. if (prevImg is null)
  146. throw new ArgumentNullException(nameof(prevImg));
  147. if (nextImg is null)
  148. throw new ArgumentNullException(nameof(nextImg));
  149. if (prevPts is null)
  150. throw new ArgumentNullException(nameof(prevPts));
  151. if (nextPts is null)
  152. throw new ArgumentNullException(nameof(nextPts));
  153. if (status is null)
  154. throw new ArgumentNullException(nameof(status));
  155. if (err is null)
  156. throw new ArgumentNullException(nameof(err));
  157. prevImg.ThrowIfDisposed();
  158. nextImg.ThrowIfDisposed();
  159. prevPts.ThrowIfDisposed();
  160. nextPts.ThrowIfNotReady();
  161. status.ThrowIfNotReady();
  162. err.ThrowIfNotReady();
  163. var winSize0 = winSize.GetValueOrDefault(new Size(21, 21));
  164. var criteria0 = criteria.GetValueOrDefault(
  165. TermCriteria.Both(30, 0.01));
  166. NativeMethods.HandleException(
  167. NativeMethods.video_calcOpticalFlowPyrLK_InputArray(
  168. prevImg.CvPtr, nextImg.CvPtr, prevPts.CvPtr, nextPts.CvPtr,
  169. status.CvPtr, err.CvPtr, winSize0, maxLevel,
  170. criteria0, (int) flags, minEigThreshold));
  171. GC.KeepAlive(prevImg);
  172. GC.KeepAlive(nextImg);
  173. GC.KeepAlive(prevPts);
  174. nextPts.Fix();
  175. status.Fix();
  176. err.Fix();
  177. }
  178. /// <summary>
  179. /// computes sparse optical flow using multi-scale Lucas-Kanade algorithm
  180. /// </summary>
  181. /// <param name="prevImg"></param>
  182. /// <param name="nextImg"></param>
  183. /// <param name="prevPts"></param>
  184. /// <param name="nextPts"></param>
  185. /// <param name="status"></param>
  186. /// <param name="err"></param>
  187. /// <param name="winSize"></param>
  188. /// <param name="maxLevel"></param>
  189. /// <param name="criteria"></param>
  190. /// <param name="flags"></param>
  191. /// <param name="minEigThreshold"></param>
  192. public static void CalcOpticalFlowPyrLK(
  193. InputArray prevImg,
  194. InputArray nextImg,
  195. Point2f[] prevPts,
  196. ref Point2f[] nextPts,
  197. out byte[] status,
  198. out float[] err,
  199. Size? winSize = null,
  200. int maxLevel = 3,
  201. TermCriteria? criteria = null,
  202. OpticalFlowFlags flags = OpticalFlowFlags.None,
  203. double minEigThreshold = 1e-4)
  204. {
  205. if (prevImg is null)
  206. throw new ArgumentNullException(nameof(prevImg));
  207. if (nextImg is null)
  208. throw new ArgumentNullException(nameof(nextImg));
  209. if (prevPts is null)
  210. throw new ArgumentNullException(nameof(prevPts));
  211. if (nextPts is null)
  212. throw new ArgumentNullException(nameof(nextPts));
  213. prevImg.ThrowIfDisposed();
  214. nextImg.ThrowIfDisposed();
  215. var winSize0 = winSize.GetValueOrDefault(new Size(21, 21));
  216. var criteria0 = criteria.GetValueOrDefault(
  217. TermCriteria.Both(30, 0.01));
  218. using var nextPtsVec = new VectorOfPoint2f(nextPts);
  219. using var statusVec = new VectorOfByte();
  220. using var errVec = new VectorOfFloat();
  221. NativeMethods.HandleException(
  222. NativeMethods.video_calcOpticalFlowPyrLK_vector(
  223. prevImg.CvPtr, nextImg.CvPtr, prevPts, prevPts.Length,
  224. nextPtsVec.CvPtr, statusVec.CvPtr, errVec.CvPtr,
  225. winSize0, maxLevel, criteria0, (int) flags, minEigThreshold));
  226. GC.KeepAlive(prevImg);
  227. GC.KeepAlive(nextImg);
  228. nextPts = nextPtsVec.ToArray();
  229. status = statusVec.ToArray();
  230. err = errVec.ToArray();
  231. }
  232. /// <summary>
  233. /// Computes a dense optical flow using the Gunnar Farneback's algorithm.
  234. /// </summary>
  235. /// <param name="prev">first 8-bit single-channel input image.</param>
  236. /// <param name="next">second input image of the same size and the same type as prev.</param>
  237. /// <param name="flow">computed flow image that has the same size as prev and type CV_32FC2.</param>
  238. /// <param name="pyrScale">parameter, specifying the image scale (&lt;1) to build pyramids for each image;
  239. /// pyrScale=0.5 means a classical pyramid, where each next layer is twice smaller than the previous one.</param>
  240. /// <param name="levels">number of pyramid layers including the initial image;
  241. /// levels=1 means that no extra layers are created and only the original images are used.</param>
  242. /// <param name="winsize">averaging window size; larger values increase the algorithm robustness to
  243. /// image noise and give more chances for fast motion detection, but yield more blurred motion field.</param>
  244. /// <param name="iterations">number of iterations the algorithm does at each pyramid level.</param>
  245. /// <param name="polyN">size of the pixel neighborhood used to find polynomial expansion in each pixel;
  246. /// larger values mean that the image will be approximated with smoother surfaces,
  247. /// yielding more robust algorithm and more blurred motion field, typically poly_n =5 or 7.</param>
  248. /// <param name="polySigma">standard deviation of the Gaussian that is used to smooth derivatives used as
  249. /// a basis for the polynomial expansion; for polyN=5, you can set polySigma=1.1,
  250. /// for polyN=7, a good value would be polySigma=1.5.</param>
  251. /// <param name="flags">operation flags that can be a combination of OPTFLOW_USE_INITIAL_FLOW and/or OPTFLOW_FARNEBACK_GAUSSIAN</param>
  252. public static void CalcOpticalFlowFarneback(InputArray prev, InputArray next,
  253. InputOutputArray flow, double pyrScale, int levels, int winsize,
  254. int iterations, int polyN, double polySigma, OpticalFlowFlags flags)
  255. {
  256. if (prev is null)
  257. throw new ArgumentNullException(nameof(prev));
  258. if (next is null)
  259. throw new ArgumentNullException(nameof(next));
  260. if (flow is null)
  261. throw new ArgumentNullException(nameof(flow));
  262. prev.ThrowIfDisposed();
  263. next.ThrowIfDisposed();
  264. flow.ThrowIfNotReady();
  265. NativeMethods.HandleException(
  266. NativeMethods.video_calcOpticalFlowFarneback(
  267. prev.CvPtr, next.CvPtr, flow.CvPtr, pyrScale, levels, winsize,
  268. iterations, polyN, polySigma, (int) flags));
  269. GC.KeepAlive(prev);
  270. GC.KeepAlive(next);
  271. flow.Fix();
  272. }
  273. /// <summary>
  274. /// Computes the Enhanced Correlation Coefficient value between two images @cite EP08 .
  275. /// </summary>
  276. /// <param name="templateImage">single-channel template image; CV_8U or CV_32F array.</param>
  277. /// <param name="inputImage">single-channel input image to be warped to provide an image similar to templateImage, same type as templateImage.</param>
  278. /// <param name="inputMask">An optional mask to indicate valid values of inputImage.</param>
  279. /// <returns></returns>
  280. public static double ComputeECC(InputArray templateImage, InputArray inputImage, InputArray? inputMask = null)
  281. {
  282. if (templateImage is null)
  283. throw new ArgumentNullException(nameof(templateImage));
  284. if (inputImage is null)
  285. throw new ArgumentNullException(nameof(inputImage));
  286. templateImage.ThrowIfDisposed();
  287. inputImage.ThrowIfDisposed();
  288. inputMask?.ThrowIfDisposed();
  289. NativeMethods.HandleException(
  290. NativeMethods.video_computeECC(
  291. templateImage.CvPtr, inputImage.CvPtr, inputMask?.CvPtr ?? IntPtr.Zero, out var ret));
  292. GC.KeepAlive(templateImage);
  293. GC.KeepAlive(inputImage);
  294. GC.KeepAlive(inputMask);
  295. return ret;
  296. }
  297. /// <summary>
  298. /// Finds the geometric transform (warp) between two images in terms of the ECC criterion @cite EP08 .
  299. /// </summary>
  300. /// <param name="templateImage">single-channel template image; CV_8U or CV_32F array.</param>
  301. /// <param name="inputImage">single-channel input image which should be warped with the final warpMatrix in
  302. /// order to provide an image similar to templateImage, same type as templateImage.</param>
  303. /// <param name="warpMatrix">floating-point \f$2\times 3\f$ or \f$3\times 3\f$ mapping matrix (warp).</param>
  304. /// <param name="motionType">parameter, specifying the type of motion</param>
  305. /// <param name="criteria">parameter, specifying the termination criteria of the ECC algorithm;
  306. /// criteria.epsilon defines the threshold of the increment in the correlation coefficient between two
  307. /// iterations(a negative criteria.epsilon makes criteria.maxcount the only termination criterion).
  308. /// Default values are shown in the declaration above.</param>
  309. /// <param name="inputMask">An optional mask to indicate valid values of inputImage.</param>
  310. /// <param name="gaussFiltSize">An optional value indicating size of gaussian blur filter; (DEFAULT: 5)</param>
  311. /// <returns></returns>
  312. public static double FindTransformECC(
  313. InputArray templateImage,
  314. InputArray inputImage,
  315. InputOutputArray warpMatrix,
  316. MotionTypes motionType,
  317. TermCriteria criteria,
  318. InputArray? inputMask = null,
  319. int gaussFiltSize = 5)
  320. {
  321. if (templateImage is null)
  322. throw new ArgumentNullException(nameof(templateImage));
  323. if (inputImage is null)
  324. throw new ArgumentNullException(nameof(inputImage));
  325. if (warpMatrix is null)
  326. throw new ArgumentNullException(nameof(warpMatrix));
  327. templateImage.ThrowIfDisposed();
  328. inputImage.ThrowIfDisposed();
  329. warpMatrix.ThrowIfDisposed();
  330. inputMask?.ThrowIfDisposed();
  331. NativeMethods.HandleException(
  332. NativeMethods.video_findTransformECC1(
  333. templateImage.CvPtr, inputImage.CvPtr, warpMatrix.CvPtr, (int)motionType,
  334. criteria, inputMask?.CvPtr ?? IntPtr.Zero, gaussFiltSize,
  335. out var ret));
  336. GC.KeepAlive(templateImage);
  337. GC.KeepAlive(inputImage);
  338. GC.KeepAlive(warpMatrix);
  339. GC.KeepAlive(inputMask);
  340. return ret;
  341. }
  342. /// <summary>
  343. /// Finds the geometric transform (warp) between two images in terms of the ECC criterion @cite EP08 .
  344. /// </summary>
  345. /// <param name="templateImage">single-channel template image; CV_8U or CV_32F array.</param>
  346. /// <param name="inputImage">single-channel input image which should be warped with the final warpMatrix in
  347. /// order to provide an image similar to templateImage, same type as templateImage.</param>
  348. /// <param name="warpMatrix">floating-point \f$2\times 3\f$ or \f$3\times 3\f$ mapping matrix (warp).</param>
  349. /// <param name="motionType">parameter, specifying the type of motion</param>
  350. /// <param name="criteria">parameter, specifying the termination criteria of the ECC algorithm;
  351. /// criteria.epsilon defines the threshold of the increment in the correlation coefficient between two
  352. /// iterations(a negative criteria.epsilon makes criteria.maxcount the only termination criterion).
  353. /// Default values are shown in the declaration above.</param>
  354. /// <param name="inputMask">An optional mask to indicate valid values of inputImage.</param>
  355. /// <returns></returns>
  356. public static double FindTransformECC(
  357. InputArray templateImage,
  358. InputArray inputImage,
  359. InputOutputArray warpMatrix,
  360. MotionTypes motionType = MotionTypes.Affine,
  361. TermCriteria? criteria = null,
  362. InputArray? inputMask = null)
  363. {
  364. if (templateImage is null)
  365. throw new ArgumentNullException(nameof(templateImage));
  366. if (inputImage is null)
  367. throw new ArgumentNullException(nameof(inputImage));
  368. if (warpMatrix is null)
  369. throw new ArgumentNullException(nameof(warpMatrix));
  370. templateImage.ThrowIfDisposed();
  371. inputImage.ThrowIfDisposed();
  372. warpMatrix.ThrowIfDisposed();
  373. inputMask?.ThrowIfDisposed();
  374. var criteriaValue = criteria.GetValueOrDefault(new TermCriteria(CriteriaTypes.Count | CriteriaTypes.Eps, 50, 0.001));
  375. NativeMethods.HandleException(
  376. NativeMethods.video_findTransformECC2(
  377. templateImage.CvPtr, inputImage.CvPtr, warpMatrix.CvPtr, (int)motionType,
  378. criteriaValue, inputMask?.CvPtr ?? IntPtr.Zero, out var ret));
  379. GC.KeepAlive(templateImage);
  380. GC.KeepAlive(inputImage);
  381. GC.KeepAlive(warpMatrix);
  382. GC.KeepAlive(inputMask);
  383. return ret;
  384. }
  385. }