From 38e6d668b1087f45198dfe633cc8ad7319e996ea Mon Sep 17 00:00:00 2001 From: Gourav Roy <34737471+themechanicalcoder@users.noreply.github.com> Date: Sun, 12 Jan 2020 14:04:59 +0530 Subject: [PATCH] Merge pull request #16276 from themechanicalcoder:video-tutorial * Added java code for meanshift and optical_flow * added java code for module video * added appropriate spaces in codes * converted absolute path to command line arguments * added spaces at appropriate places --- .../video/meanshift/meanshift.markdown | 16 ++++ .../video/optical_flow/optical_flow.markdown | 18 ++++ .../video/table_of_content_video.markdown | 4 +- .../video/meanshift/CamshiftDemo.java | 75 +++++++++++++++ .../video/meanshift/MeanshiftDemo.java | 70 ++++++++++++++ .../video/optical_flow/OpticalFlowDemo.java | 96 +++++++++++++++++++ .../optical_flow/OpticalFlowDenseDemo.java | 72 ++++++++++++++ 7 files changed, 349 insertions(+), 2 deletions(-) create mode 100644 samples/java/tutorial_code/video/meanshift/CamshiftDemo.java create mode 100644 samples/java/tutorial_code/video/meanshift/MeanshiftDemo.java create mode 100644 samples/java/tutorial_code/video/optical_flow/OpticalFlowDemo.java create mode 100644 samples/java/tutorial_code/video/optical_flow/OpticalFlowDenseDemo.java diff --git a/doc/tutorials/video/meanshift/meanshift.markdown b/doc/tutorials/video/meanshift/meanshift.markdown index d2649f6dc1..5b2d789ac2 100644 --- a/doc/tutorials/video/meanshift/meanshift.markdown +++ b/doc/tutorials/video/meanshift/meanshift.markdown @@ -57,6 +57,14 @@ low light, low light values are discarded using **cv.inRange()** function. @include samples/python/tutorial_code/video/meanshift/meanshift.py @end_toggle +@add_toggle_java +- **Downloadable code**: Click + [here](https://github.com/opencv/opencv/tree/3.4/samples/java/tutorial_code/video/meanshift/MeanshiftDemo.java) + +- **Code at glance:** + @include samples/java/tutorial_code/video/meanshift/MeanshiftDemo.java +@end_toggle + Three frames in a video I used is given below: ![image](images/meanshift_result.jpg) @@ -98,6 +106,14 @@ parameters (used to be passed as search window in next iteration). See the code @include samples/python/tutorial_code/video/meanshift/camshift.py @end_toggle +@add_toggle_java +- **Downloadable code**: Click + [here](https://github.com/opencv/opencv/tree/3.4/samples/java/tutorial_code/video/meanshift/CamshiftDemo.java) + +- **Code at glance:** + @include samples/java/tutorial_code/video/meanshift/CamshiftDemo.java +@end_toggle + Three frames of the result is shown below: ![image](images/camshift_result.jpg) diff --git a/doc/tutorials/video/optical_flow/optical_flow.markdown b/doc/tutorials/video/optical_flow/optical_flow.markdown index a3e3245fba..d7a6896d1b 100644 --- a/doc/tutorials/video/optical_flow/optical_flow.markdown +++ b/doc/tutorials/video/optical_flow/optical_flow.markdown @@ -109,6 +109,15 @@ below: @include samples/python/tutorial_code/video/optical_flow/optical_flow.py @end_toggle + +@add_toggle_java +- **Downloadable code**: Click + [here](https://github.com/opencv/opencv/tree/3.4/samples/java/tutorial_code/video/optical_flow/OpticalFlowDemo.java) + +- **Code at glance:** + @include samples/java/tutorial_code/video/optical_flow/OpticalFlowDemo.java +@end_toggle + (This code doesn't check how correct are the next keypoints. So even if any feature point disappears in image, there is a chance that optical flow finds the next point which may look close to it. So actually for a robust tracking, corner points should be detected in particular intervals. OpenCV @@ -151,6 +160,15 @@ corresponds to Value plane. See the code below: @end_toggle +@add_toggle_java +- **Downloadable code**: Click + [here](https://github.com/opencv/opencv/tree/3.4/samples/java/tutorial_code/video/optical_flow/OpticalFlowDenseDemo.java) + +- **Code at glance:** + @include samples/java/tutorial_code/video/optical_flow/OpticalFlowDenseDemo.java +@end_toggle + + See the result below: ![image](images/opticalfb.jpg) diff --git a/doc/tutorials/video/table_of_content_video.markdown b/doc/tutorials/video/table_of_content_video.markdown index 92a5315355..1a80f716da 100644 --- a/doc/tutorials/video/table_of_content_video.markdown +++ b/doc/tutorials/video/table_of_content_video.markdown @@ -17,12 +17,12 @@ tracking and foreground extractions. - @subpage tutorial_meanshift - *Languages:* C++, Python + *Languages:* C++, Java, Python Learn how to use the Meanshift and Camshift algorithms to track objects in videos. - @subpage tutorial_optical_flow - *Languages:* C++, Python + *Languages:* C++, Java, Python We will learn how to use optical flow methods to track sparse features or to create a dense representation. diff --git a/samples/java/tutorial_code/video/meanshift/CamshiftDemo.java b/samples/java/tutorial_code/video/meanshift/CamshiftDemo.java new file mode 100644 index 0000000000..6717446a7f --- /dev/null +++ b/samples/java/tutorial_code/video/meanshift/CamshiftDemo.java @@ -0,0 +1,75 @@ +import java.util.Arrays; +import org.opencv.core.*; +import org.opencv.highgui.HighGui; +import org.opencv.imgproc.Imgproc; +import org.opencv.video.Video; +import org.opencv.videoio.VideoCapture; + + +class Camshift { + public void run(String[] args) { + String filename = args[0]; + VideoCapture capture = new VideoCapture(filename); + if (!capture.isOpened()) { + System.out.println("Unable to open file!"); + System.exit(-1); + } + + Mat frame = new Mat(), hsv_roi = new Mat(), mask = new Mat(), roi; + + // take the first frame of the video + capture.read(frame); + + //setup initial location of window + Rect track_window = new Rect(300, 200, 100, 50); + + // set up the ROI for tracking + roi = new Mat(frame, track_window); + Imgproc.cvtColor(roi, hsv_roi, Imgproc.COLOR_BGR2HSV); + Core.inRange(hsv_roi, new Scalar(0, 60, 32), new Scalar(180, 255, 255), mask); + + MatOfFloat range = new MatOfFloat(0, 256); + Mat roi_hist = new Mat(); + MatOfInt histSize = new MatOfInt(180); + MatOfInt channels = new MatOfInt(0); + Imgproc.calcHist(Arrays.asList(hsv_roi), channels, mask, roi_hist, histSize, range); + Core.normalize(roi_hist, roi_hist, 0, 255, Core.NORM_MINMAX); + + // Setup the termination criteria, either 10 iteration or move by atleast 1 pt + TermCriteria term_crit = new TermCriteria(TermCriteria.EPS | TermCriteria.COUNT, 10, 1); + + while (true) { + Mat hsv = new Mat() , dst = new Mat(); + capture.read(frame); + if (frame.empty()) { + break; + } + Imgproc.cvtColor(frame, hsv, Imgproc.COLOR_BGR2HSV); + Imgproc.calcBackProject(Arrays.asList(hsv), channels, roi_hist, dst, range, 1); + + // apply camshift to get the new location + RotatedRect rot_rect = Video.CamShift(dst, track_window, term_crit); + + // Draw it on image + Point[] points = new Point[4]; + rot_rect.points(points); + for (int i = 0; i < 4 ;i++) { + Imgproc.line(frame, points[i], points[(i+1)%4], new Scalar(255, 0, 0),2); + } + + HighGui.imshow("img2", frame); + int keyboard = HighGui.waitKey(30); + if (keyboard == 'q'|| keyboard == 27) { + break; + } + } + System.exit(0); + } +} + +public class CamshiftDemo { + public static void main(String[] args) { + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + new Camshift().run(args); + } +} diff --git a/samples/java/tutorial_code/video/meanshift/MeanshiftDemo.java b/samples/java/tutorial_code/video/meanshift/MeanshiftDemo.java new file mode 100644 index 0000000000..5fbdd0efff --- /dev/null +++ b/samples/java/tutorial_code/video/meanshift/MeanshiftDemo.java @@ -0,0 +1,70 @@ +import java.util.Arrays; +import org.opencv.core.*; +import org.opencv.highgui.HighGui; +import org.opencv.imgproc.Imgproc; +import org.opencv.video.Video; +import org.opencv.videoio.VideoCapture; + + +class Meanshift { + public void run(String[] args) { + String filename = args[0]; + VideoCapture capture = new VideoCapture(filename); + if (!capture.isOpened()) { + System.out.println("Unable to open file!"); + System.exit(-1); + } + Mat frame = new Mat(), hsv_roi = new Mat(), mask = new Mat(), roi; + + // take the first frame of the video + capture.read(frame); + + //setup initial location of window + Rect track_window = new Rect(300, 200, 100, 50); + + // setup initial location of window + roi = new Mat(frame, track_window); + Imgproc.cvtColor(roi, hsv_roi, Imgproc.COLOR_BGR2HSV); + Core.inRange(hsv_roi, new Scalar(0, 60, 32), new Scalar(180, 255, 255), mask); + + MatOfFloat range = new MatOfFloat(0, 256); + Mat roi_hist = new Mat(); + MatOfInt histSize = new MatOfInt(180); + MatOfInt channels = new MatOfInt(0); + Imgproc.calcHist(Arrays.asList(hsv_roi), channels, mask, roi_hist, histSize, range); + Core.normalize(roi_hist, roi_hist, 0, 255, Core.NORM_MINMAX); + + // Setup the termination criteria, either 10 iteration or move by atleast 1 pt + TermCriteria term_crit = new TermCriteria(TermCriteria.EPS | TermCriteria.COUNT, 10, 1); + + while (true) { + Mat hsv = new Mat() , dst = new Mat(); + capture.read(frame); + if (frame.empty()) { + break; + } + Imgproc.cvtColor(frame, hsv, Imgproc.COLOR_BGR2HSV); + Imgproc.calcBackProject(Arrays.asList(hsv), channels, roi_hist, dst, range, 1); + + // apply meanshift to get the new location + Video.meanShift(dst, track_window, term_crit); + + // Draw it on image + Imgproc.rectangle(frame, track_window, new Scalar(255, 0, 0), 2); + HighGui.imshow("img2", frame); + + int keyboard = HighGui.waitKey(30); + if (keyboard == 'q' || keyboard == 27) { + break; + } + } + System.exit(0); + } +} + +public class MeanshiftDemo { + public static void main(String[] args) { + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + new Meanshift().run(args); + } +} diff --git a/samples/java/tutorial_code/video/optical_flow/OpticalFlowDemo.java b/samples/java/tutorial_code/video/optical_flow/OpticalFlowDemo.java new file mode 100644 index 0000000000..cf9f678869 --- /dev/null +++ b/samples/java/tutorial_code/video/optical_flow/OpticalFlowDemo.java @@ -0,0 +1,96 @@ +import java.util.ArrayList; +import java.util.Random; +import org.opencv.core.*; +import org.opencv.highgui.HighGui; +import org.opencv.imgproc.Imgproc; +import org.opencv.video.Video; +import org.opencv.videoio.VideoCapture; + +class OptFlow { + public void run(String[] args) { + String filename = args[0]; + VideoCapture capture = new VideoCapture(filename); + if (!capture.isOpened()) { + System.out.println("Unable to open this file"); + System.exit(-1); + } + + + // Create some random colors + Scalar[] colors = new Scalar[100]; + Random rng = new Random(); + for (int i = 0 ; i < 100 ; i++) { + int r = rng.nextInt(256); + int g = rng.nextInt(256); + int b = rng.nextInt(256); + colors[i] = new Scalar(r, g, b); + } + + Mat old_frame = new Mat() , old_gray = new Mat(); + + // Since the function Imgproc.goodFeaturesToTrack requires MatofPoint + // therefore first p0MatofPoint is passed to the function and then converted to MatOfPoint2f + MatOfPoint p0MatofPoint = new MatOfPoint(); + capture.read(old_frame); + Imgproc.cvtColor(old_frame, old_gray, Imgproc.COLOR_BGR2GRAY); + Imgproc.goodFeaturesToTrack(old_gray, p0MatofPoint,100,0.3,7, new Mat(),7,false,0.04); + + MatOfPoint2f p0 = new MatOfPoint2f(p0MatofPoint.toArray()) , p1 = new MatOfPoint2f(); + + // Create a mask image for drawing purposes + Mat mask = Mat.zeros(old_frame.size(), old_frame.type()); + + while (true) { + Mat frame = new Mat(), frame_gray = new Mat(); + capture.read(frame); + if (frame.empty()) { + break; + } + + Imgproc.cvtColor(frame, frame_gray, Imgproc.COLOR_BGR2GRAY); + + // calculate optical flow + MatOfByte status = new MatOfByte(); + MatOfFloat err = new MatOfFloat(); + TermCriteria criteria = new TermCriteria(TermCriteria.COUNT + TermCriteria.EPS,10,0.03); + Video.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, p1, status, err, new Size(15,15),2, criteria); + + byte StatusArr[] = status.toArray(); + Point p0Arr[] = p0.toArray(); + Point p1Arr[] = p1.toArray(); + ArrayList good_new = new ArrayList<>(); + + for (int i = 0; i flow_parts = new ArrayList<>(2); + Core.split(flow, flow_parts); + Mat magnitude = new Mat(), angle = new Mat(), magn_norm = new Mat(); + Core.cartToPolar(flow_parts.get(0), flow_parts.get(1), magnitude, angle,true); + Core.normalize(magnitude, magn_norm,0.0,1.0, Core.NORM_MINMAX); + float factor = (float) ((1.0/360.0)*(180.0/255.0)); + Mat new_angle = new Mat(); + Core.multiply(angle, new Scalar(factor), new_angle); + + //build hsv image + ArrayList _hsv = new ArrayList<>() ; + Mat hsv = new Mat(), hsv8 = new Mat(), bgr = new Mat(); + + _hsv.add(new_angle); + _hsv.add(Mat.ones(angle.size(), CvType.CV_32F)); + _hsv.add(magn_norm); + Core.merge(_hsv, hsv); + hsv.convertTo(hsv8, CvType.CV_8U, 255.0); + Imgproc.cvtColor(hsv8, bgr, Imgproc.COLOR_HSV2BGR); + + HighGui.imshow("frame2", bgr); + + int keyboard = HighGui.waitKey(30); + if (keyboard == 'q' || keyboard == 27) { + break; + } + prvs = next; + } + System.exit(0); + } +} + +public class OpticalFlowDenseDemo { + public static void main(String[] args) { + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + new OptFlowDense().run(args); + } +}