|
|
|
package com.zhonglai.luhui.smart.feeder.service;
|
|
|
|
|
|
|
|
import com.zhonglai.luhui.smart.feeder.config.OpenCVConfig;
|
|
|
|
import com.zhonglai.luhui.smart.feeder.util.OpenCVUtils;
|
|
|
|
import org.opencv.core.Core;
|
|
|
|
import org.opencv.core.Mat;
|
|
|
|
import org.opencv.videoio.VideoCapture;
|
|
|
|
import org.opencv.imgproc.Imgproc;
|
|
|
|
import org.opencv.core.MatOfPoint;
|
|
|
|
import org.opencv.core.Scalar;
|
|
|
|
import org.opencv.core.CvType;
|
|
|
|
import org.opencv.core.Rect;
|
|
|
|
|
|
|
|
import javax.swing.*;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
public class OpenCVService {
|
|
|
|
public static void main(String[] args) {
|
|
|
|
OpenCVConfig.loadOpenCv(args);
|
|
|
|
readVideoCaptureForVideo("C:/Users/123/Pictures/图片识别/6月30日.mp4");
|
|
|
|
}
|
|
|
|
public static void readVideoCaptureForVideo(String videoPath)
|
|
|
|
{
|
|
|
|
// 创建VideoCapture对象
|
|
|
|
VideoCapture videoCapture = new VideoCapture();
|
|
|
|
boolean isopen = videoCapture.open(videoPath);
|
|
|
|
System.out.println(isopen);
|
|
|
|
// 检查视频是否成功打开
|
|
|
|
if (!videoCapture.isOpened()) {
|
|
|
|
System.out.println("无法打开视频文件");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// 背景帧
|
|
|
|
Mat backgroundFrame = new Mat();
|
|
|
|
|
|
|
|
// 初始阈值范围
|
|
|
|
double minAreaThreshold = Double.MAX_VALUE;
|
|
|
|
double maxAreaThreshold = 0;
|
|
|
|
|
|
|
|
// 逐帧处理视频
|
|
|
|
Mat frame = new Mat();
|
|
|
|
while (videoCapture.read(frame)) {
|
|
|
|
// 背景差分
|
|
|
|
Mat diffFrame = new Mat();
|
|
|
|
Core.absdiff(frame, backgroundFrame, diffFrame);
|
|
|
|
|
|
|
|
// 灰度转换
|
|
|
|
Mat grayFrame = new Mat();
|
|
|
|
Imgproc.cvtColor(diffFrame, grayFrame, Imgproc.COLOR_BGR2GRAY);
|
|
|
|
|
|
|
|
// 阈值处理
|
|
|
|
Mat thresholdFrame = new Mat();
|
|
|
|
Imgproc.threshold(grayFrame, thresholdFrame, 30, 255, Imgproc.THRESH_BINARY);
|
|
|
|
|
|
|
|
// 边缘检测
|
|
|
|
Mat edges = new Mat();
|
|
|
|
Imgproc.Canny(thresholdFrame, edges, 100, 200);
|
|
|
|
|
|
|
|
// 轮廓检测
|
|
|
|
List<MatOfPoint> contours = new ArrayList<>();
|
|
|
|
Mat hierarchy = new Mat();
|
|
|
|
Imgproc.findContours(edges, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
|
|
|
|
|
|
|
|
// 更新阈值范围
|
|
|
|
for (MatOfPoint contour : contours) {
|
|
|
|
double area = Imgproc.contourArea(contour);
|
|
|
|
if (area > maxAreaThreshold) {
|
|
|
|
maxAreaThreshold = area;
|
|
|
|
}
|
|
|
|
if (area < minAreaThreshold) {
|
|
|
|
minAreaThreshold = area;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 根据阈值范围选择适当的阈值
|
|
|
|
double thresholdValue = (maxAreaThreshold + minAreaThreshold) / 2.0;
|
|
|
|
|
|
|
|
// 绘制轮廓
|
|
|
|
Mat contourImage = new Mat(frame.size(), CvType.CV_8UC3, new Scalar(0, 0, 0));
|
|
|
|
Imgproc.drawContours(contourImage, contours, -1, new Scalar(0, 255, 0), 2);
|
|
|
|
|
|
|
|
// 提取鱼群区域
|
|
|
|
for (MatOfPoint contour : contours) {
|
|
|
|
double area = Imgproc.contourArea(contour);
|
|
|
|
if (area > thresholdValue) {
|
|
|
|
// 对于满足面积阈值的轮廓,可以进一步处理或分析
|
|
|
|
// 例如,计算鱼群数量、中心位置等信息
|
|
|
|
// ...
|
|
|
|
|
|
|
|
// 在原图上绘制鱼群区域
|
|
|
|
Rect boundingRect = Imgproc.boundingRect(contour);
|
|
|
|
Imgproc.rectangle(frame, boundingRect.tl(), boundingRect.br(), new Scalar(0, 255, 0), 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 重置阈值范围
|
|
|
|
minAreaThreshold = Double.MAX_VALUE;
|
|
|
|
maxAreaThreshold = 0;
|
|
|
|
|
|
|
|
// 在图像上显示结果
|
|
|
|
displayImage(frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 显示图像
|
|
|
|
private static void displayImage(Mat image) {
|
|
|
|
// 将Mat图像转换为BufferedImage
|
|
|
|
BufferedImage bufferedImage = OpenCVUtils.matToBufferedImage(image);
|
|
|
|
|
|
|
|
// 在标签上显示图像
|
|
|
|
new ImageIcon(bufferedImage);
|
|
|
|
|
|
|
|
// 更新窗口
|
|
|
|
}
|
|
|
|
} |
...
|
...
|
|