在這裡我參考了網路上的資料加上修改實測,展示一個簡單的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 下載分享
參考資料: