1.讀取本地視頻流,pom依賴
依賴於 org.bytedeco下的javacv/opencv/ffmpeg 包
<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.4.3</version> </dependency> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv</artifactId> <version>3.4.3-1.4.3</version> <classifier>linux-x86_64</classifier> </dependency> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>ffmpeg</artifactId> <version>4.0.2-1.4.3</version> <classifier>linux-x86_64</classifier> </dependency>
2.讀取本地視頻流並解幀為 opencv_core.Mat
File file = new File("/home/lab/javacv/t11.mp4"); FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(file); grabber.start(); // 解幀為opencv_core.Mat List<opencv_core.Mat> mats = new ArrayList<>(); for (int i = 0; i < grabber.getLengthInFrames(); i++) { Frame frame = grabber.grabImage(); OpenCVFrameConverter.ToMat toMat = new OpenCVFrameConverter.ToMat(); opencv_core.Mat mat = toMat.convert(frame); if (mat != null) { mats.add(mat.clone()); } } grabber.stop();
3.獲取32位dhash特征
dhash特征提取思路,圖片Mat轉為單通道的灰度圖,並重置為5*5的Size,最后將其轉儲為長度為 25 的byte數組用以求取32位dhash特征
// 聲明空的灰度圖 Mat opencv_core.Mat grayImg = new opencv_core.Mat(mat.rows(), mat.cols(), opencv_imgcodecs.IMREAD_GRAYSCALE); // 轉儲為灰度圖 opencv_imgproc.cvtColor(mat, grayImg, opencv_imgproc.COLOR_RGB2GRAY); // 修改Mat長寬size opencv_core.Mat resizedImg = new opencv_core.Mat(); opencv_core.Size size = new opencv_core.Size(5,5); opencv_imgproc.resize(grayImg,resizedImg,size); // 轉為 5*5 byte 數組 byte[] bytePixels = new byte[5 * 5]; resizedImg.data().get(bytePixels); int[] pixels = new int[bytePixels.length]; for (int i=0; i<pixels.length; i++) { pixels[i] = bytePixels[i] & 0xff; } // 獲取32位dhash特征 int feature = 0; for (int j=0; j<4; j++) { for (int i=0; i<4; i++) { int colBit = pixels[i*5+j] > pixels[(i+1)*5+j] ? 1 : 0; feature = (feature << 1) + colBit; int rowBit = pixels[i*5+j] > pixels[i*5+j+1] ? 1 : 0 ; feature = (feature << 1) + rowBit; } }
多線程部分,可參考該博: https://www.cnblogs.com/nyatom/p/10119306.html