在這裡我參考了網路上的資料加上修改實測,展示一個簡單的OpenCV範例:
程式語言 : Java
需求:
調用電腦本身的攝影機,在UI上顯示即時截取的畫面,並在辨視出人臉的地方加上方框,並將人臉部份儲存至本地電腦上。
到這裡下載OpenCV,我下載的是 3.4.1 的Win pack版本,下載後執行,它會解壓縮生成一個opencv資料,打開它後,
會看到所須的jar檔及dll檔:
opencv-341.jar
並且在x64和x86資料夾內有不同位元的windows dll檔:
opencv_java341.dll
以Eclipse來示範,除了加入opencv0341.jar到lib後,還要如下圖設定Native library location為dll檔所在的資料夾路徑
接下來是程式的部份
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.util.Calendar;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.Videoio;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class OpenCV_Test extends Application{
//是否正在截取攝影機影像
private boolean isStart = false;
private VideoCapture videoCapture;
private ScheduledExecutorService scheduledExecutorService;
// JavaFX 元件
private BorderPane rootNode;
private VBox vbox;
private ImageView imageView;
private Button startStopBtn;
String startText = "Start";
String stopText = "Stop";
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
startStopBtn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
if (!isStart) {
startStopBtn.setText(stopText);
videoCapture.open(0);
videoCapture.set(Videoio.CAP_PROP_FRAME_WIDTH, 640);
videoCapture.set(Videoio.CAP_PROP_FRAME_HEIGHT, 480);
if (videoCapture.isOpened()) {
isStart = true;
//建立設定截取攝影機的thread
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
imageView.setImage(captureImage());
}
}, 0, 16, TimeUnit.MILLISECONDS);
}else {
System.err.println("Error: Can not open camera.");
}
}else {
startStopBtn.setText(startText);
isStart = false;
scheduledExecutorService.shutdown();
try {
//確保scheduledExecutorService有正確關閉排程
while(!scheduledExecutorService.awaitTermination(30, TimeUnit.MILLISECONDS)) {
System.out.println("Not close thread yet");
}
} catch (InterruptedException e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
videoCapture.release();
imageView.setImage(null);
}
}
});
//UI畫面
Scene scene = new Scene(rootNode, 800, 640);
primaryStage.setTitle("OpenCV Test");
primaryStage.setScene(scene);
primaryStage.show();
}
//UI畫面設定
@Override
public void init() throws Exception {
super.init();
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
videoCapture = new VideoCapture();
rootNode = new BorderPane();
vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
rootNode.setCenter(vbox);
imageView = new ImageView();
imageView.setFitWidth(640);
imageView.setFitHeight(480);
imageView.setPreserveRatio(true);
startStopBtn = new Button(startText);
vbox.getChildren().addAll(imageView, startStopBtn);
}
//程式關閉時關閉攝影機
@Override
public void stop() throws Exception {
if (videoCapture.isOpened()) {
videoCapture.release();
}
super.stop();
}
private Image captureImage() {
Image capturedImage = null;
if (videoCapture.isOpened()) {
Mat mat = new Mat();
videoCapture.read(mat);
if (!mat.empty()) {
MatOfByte buffer = new MatOfByte();
//偵測人臉,截取人臉部份存圖,
//並在要顯示在畫面上的影像用矩形標示人臉部份
detectDrawAndSaveFace(mat);
Imgcodecs.imencode(".png", mat, buffer);
capturedImage = new Image(new ByteArrayInputStream(buffer.toArray()));
}
}
return capturedImage;
}
//臉部偵測
private void detectDrawAndSaveFace(Mat image) {
CascadeClassifier faceDetector = new CascadeClassifier();
faceDetector.load("D:\\JavaLib\\opencv\\sources\\data\\haarcascades_cuda\\haarcascade_frontalface_alt2.xml");
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(image, faceDetections);
for (Rect rect : faceDetections.toArray())
{
//截detect到人臉的區域,將區域內的圖存檔
Mat faceImage = new Mat(image, rect);
String outputDir = "D:\\detectedFaces";
String outputFilePath = outputDir + "\\detectedFace_" + Calendar.getInstance().getTimeInMillis() + ".png";
Imgcodecs.imwrite(outputFilePath, faceImage);
//在detect到人臉的區域上畫上矩形邊框,顯示在螢幕上的ImageView上
Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0));
}
}
}
Opencv 3.4.1 Win pack 下載分享
參考資料:












