수색…


통사론

  • CascadeClassifier cascade = 새로운 CascadeClassifier ( "cascade.xml"); // cascade.xml로부터 계단식 분류자를 생성한다.
  • 매트 이미지 = Imgcodecs.imread ( "image.png"); // image.png를 Mat (Matrix) 객체로 변환합니다.
  • MatOfRect 검출 = 새로운 MatOfRect (); // 감지 클래스의 출력으로 사용되는 빈 MatOfRect (Matrix of Rectangle) 파일을 만듭니다.
  • detections.toArray (); // 반복 할 수있는 Rect 객체의 배열을 반환합니다.
  • imgproc.rectangle (이미지, 새 포인트 (rect.x, rect.y), 새 포인트 (rect.x + rect.width, rect.y + rect.height), 새 스칼라 (0, 255, 0)); // 첫 번째 Point의 x 및 y 위치에서 두 번째 Point의 x 및 y 위치에있는 녹색 윤곽선을 Mat 객체 "image"에 그립니다. "rect"는 일반적으로 detects.toArray ()가 제공하는 Rect 객체입니다. OpenCV의 Point 클래스를 사용합니다.
  • Imgcodecs.imwrite ( "output.png", image); // 수정 된 Mat 객체 "image"를 "output.png"에 씁니다.
  • CascadeClassifier.detectMultiScale (이미지, 감지); // Mat 객체 "image"의 객체를 탐지하여 MatOfRect 객체 "detects"에 출력합니다.
  • CascadeClassifier.detectMultiScale (이미지, 감지, scaleFactor , minNeighbors , 플래그 , minSize , maxSize ); // 추가 매개 변수로 탐지를 수행합니다. 아래 세부 정보를 참조하십시오.
  • Imgproc.ellipse (이미지, 중심, , 0, 0, 360, 새 스칼라 (255, 0, 255), thickness , lineType , 0); // 점 center 의 이미지에 타원을 그립니다. OpenCV의 Point 클래스를 사용합니다.

매개 변수

매개 변수 세부
scaleFactor 각 이미지 크기에서 이미지 크기가 얼마나 줄어 듭니다. 기본값 = 1.1
minNeighbors 후보 사각형을 탐지 된 객체로 선택하기 전에 얼마나 많은 이웃들을 가져야하는지 나타냅니다. 기본값 = 4
깃발 레거시 플래그. 대부분의 경우이 값을 0 으로 설정해야합니다. 기본값 = 0
최소 크기 후보 직사각형이 될 수있는 최소 크기. 이것은 OpenCV의 Size 클래스를 사용합니다. 탐지 시간과 CPU 사용량을 줄이거 나 오 탐지를 줄이는 데 사용할 수 있습니다.
최대 크기 후보 직사각형의 최대 크기입니다. 이것은 OpenCV의 Size 클래스를 사용합니다. 탐지 시간과 CPU 사용량을 줄이거 나 오 탐지를 줄이는 데 사용할 수 있습니다.
OpenCV의 Size 클래스를 사용합니다. 타원의 폭과 높이를 정의합니다.
두께 선의 두께 (픽셀 단위)입니다.
lineType 다양한 매개 변수가 있습니다. 0 은 실선, 8 은 8 연결 선, 4 는 4 연결 선, CV_AA 는 앤티 엘리 어싱 된 선입니다. 기본값 = 8

정적 이미지 가져 오기, 항목 감지 및 결과 출력

이 예제에서는 OpenCV 3.1을 사용합니다.

import org.opencv.core.Mat;
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;

public class Classifier {
    private CascadeClassifier diceCascade = new
        CascadeClassifier("res/newMethod/diceCascade.xml");
    private Mat image;
    private String loc = "path/to/image.png";
    private String output = "path/to/output.png";

    public void detImg() {
    
        Mat image = Imgcodecs.imread(loc); // Reads the image
    
        MatOfRect diceDetections = new MatOfRect(); // Output container
        diceCascade.detectMultiScale(image, diceDetections); // Performs the detection
    
        // Draw a bounding box around each detection.
        for (Rect rect : diceDetections.toArray()) {
            Imgproc.rectangle(image, new Point(rect.x, rect.y),
                new Point(rect.x + rect.width, rect.y + rect.height),
                new Scalar(0, 255, 0));
        }
    
        // Save the visualized detection.
        Imgcodecs.imwrite(output, image);
    
    }
}

diceDetections.toArray() 의해 반환 된 Rect[] 는 반복 될 수 있습니다. 배열의 각 Rect 에는 x , y , widthheight 네 가지 기본 속성이 있습니다. xy 는 사각형의 상단 왼쪽 위치를 정의하고 widthheight 는 사각형의 widthheightint 를 반환합니다. 이미지에 직사각형을 그릴 때 사용됩니다. Imgproc.rectangle 함수의 최소 필수 매개 변수는 다음과 같습니다.

Imgproc.rectangle(Mat image, Point start, Point end, Scalar color);

Point 모두 왼쪽 상단 모서리와 오른쪽 하단 모서리의 위치에 사용됩니다. 이 위치는 첫 번째 매개 변수로 제공되는 이미지에 절대적 이며 서로가 아닙니다. 따라서 end 을 올바르게 정의하려면 width 또는 height 이외에 사각형의 x 또는 y 위치를 모두 추가해야합니다.

이러한 매개 변수에 사용 된 Point 클래스는 Java 표준 라이브러리의 Point 클래스가 아닙니다 . 대신 OpenCV의 Point 클래스를 가져와야합니다!

비디오 장치에서 이미지 감지하기

이 예제에서는 VideoCapture 클래스를 사용하여 웹캠에서 이미지를 가져 와서 이미지에 저장합니다.

import org.opencv.core.Mat;
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;

public class Classifier {
    private CascadeClassifier diceCascade = new
        CascadeClassifier("res/newMethod/diceCascade.xml");
    private Mat image;
    private String loc = "path/to/image.png";
    private String output = "path/to/output.png";
    private VideoCapture vc = new VideoCapture();

    public void detImg() {
        vc.open(0); // Opens the video stream

        Mat image = new Mat(); // Creates an empty matrix
        vc.read(image); // Reads the image from the video stream and
            writes it to the image matrix.
    
        MatOfRect diceDetections = new MatOfRect(); // Output container
        diceCascade.detectMultiScale(image, diceDetections); // Performs the detection
    
        // Draw a bounding box around each detection.
        for (Rect rect : diceDetections.toArray()) {
            Imgproc.rectangle(image, new Point(rect.x, rect.y),
                new Point(rect.x + rect.width, rect.y + rect.height),
                new Scalar(0, 255, 0));
        }
    
        // Save the visualized detection.
        Imgcodecs.imwrite(output, image);

        vc.release(); // Closes the stream.
    
    }
}

Mat 객체를 BufferedImage 객체로 변환

Daniel Baggio의이 예제는 이 StackExchange 응답 에서 직접 가져 왔지만 가시성을 위해 재 게시되었습니다.

이 클래스는 Mat 객체를 취해 javax.swing 라이브러리가 사용하는 BufferedImage 객체를 반환합니다. 이것은 Graphics 객체가 이미지를 그리는 데 사용할 수 있습니다.

private BufferedImage toBufferedImage(Mat m) {
    if (!m.empty()) {
        int type = BufferedImage.TYPE_BYTE_GRAY;
        if (m.channels() > 1) {
            type = BufferedImage.TYPE_3BYTE_BGR;
        }
        int bufferSize = m.channels() * m.cols() * m.rows();
        byte[] b = new byte[bufferSize];
        m.get(0, 0, b); // get all the pixels
        BufferedImage image = new BufferedImage(m.cols(), m.rows(), type);
        final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        System.arraycopy(b, 0, targetPixels, 0, b.length);
        return image;
    }
    
    return null;
}

탐지 내 탐지

이 예제에서는 거푸집과 주사위의 검은 반점 (핍)을 객체로 사용합니다. 예제가 꽤 길기 때문에 먼저 몇 가지 주요 개념을 설명하는 것이 예제를 이해하는 데 중요합니다.

첫 번째 예제 인 "정적 이미지 가져 오기, 항목 감지 및 결과 출력"을 이해합니다. OpenCV가 직사각형을 그리는 방법을 이해하는 데 중요합니다.

다음 이미지를 살펴보십시오.

여기에 이미지 설명을 입력하십시오.

우리는 더 많은 탐지를 적용하기위한 기반으로 탐지 된 영역을 사용하는 하위 이미징 방법을 사용할 것입니다. 이것은 우리 주사위에있는 주사위와 같이 우리가 탐지 할 수있는 다른 물체 안에 항상 물체가있을 때만 가능합니다. 이 방법에는 다음과 같은 몇 가지 이점이 있습니다.

  • 전체 이미지를 스캔하는 대신, 우리는 객체가있을 것임을 알 수있는 영역 만 스캔하면됩니다.
  • 탐지 영역 외부에서 오 탐지 가능성을 제거합니다.

우리는 먼저 커다란 객체 (이 경우 주사위)를 포함하는 MatOfRect 객체를 MatOfRect 위해 전체 이미지에 대해 하나의 캐스케이드 분류 자 ​​검사를 적용하여이 작업을 수행합니다. 그런 다음 toArray() 함수에 의해 지정된 Rect[] 배열을 MatOfRect 객체에서 MatOfRect 합니다. 이 Rect 객체는 원본 이미지에서 Rect 객체의 속성 ( x, y, width, height )으로 "잘라내 기"는 임시 Mat 객체를 만드는 데 사용됩니다. 여기서 임시 Mat 객체에 대한 감지를 수행 할 수 있습니다. 즉, 분류 자에게 대신 이미지의 주사위 부분에 대해서만 감지를 수행하고 전체 이미지에서 감지를 수행하여 얻은 Rect 객체를 사용하여 각 주사위의 위치를 ​​지정합니다.

그러나 Rect 객체 (pips)는 이미지 자체가 아닌 주사위에 상대적인 속성 Rect 집니다. 우리는 주사위의 위치를 보여주는 실제 이미지에 사각형을 그릴 때이 문제를 해결하기 위해, 우리는 모두 추가 dice.xdice.y 시작으로 Point .

import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;

public class Classifier {

    private CascadeClassifier diceCascade =
        new CascadeClassifier("res/newMethod/diceCascade.xml");
    private CascadeClassifier pipCascade =
        new CascadeClassifier("res/newMethod/pipCascade6.xml");
    private VideoCapture vc = new VideoCapture();
    private Mat image;

    public void openVC(int index) {
        vc.open(index);
    }

    public void closeVC() {
        vc.close();
    }

    public Mat getNextImage() {
        image = new Mat();
        vc.read(image); // Sets the matrix to the current livestream frame.
        
        MatOfRect diceDetections = new MatOfRect(); // Output container
    
        // See syntax for explainations on addition parameters
        diceCascade.detectMultiScale(image, diceDetections, 1.1, 4, 0, new Size(20, 20),
            new Size(38, 38));
        
        // Iterates for every Dice ROI
        for (int i = 0; i < diceDetections.toArray().length; i++) {
            Rect diceRect = diceDetections.toArray()[i];
            
            // Draws rectangles around our detected ROI
            Point startingPoint = new Point(diceRect.x, diceRect.y);
            Point endingPoint = new Point(diceRect.x + diceRect.width,
                diceRect.y + diceRect.height);
            Imgproc.rectangle(image, startingPoint, endingPoint, new Scalar(255, 255, 0));
            
            MatOfRect pipDetections = new MatOfRect();
            
            pipCascade.detectMultiScale(image.submat(diceRect), pipDetections, 1.01, 4, 0,
                new Size(2, 2), new Size(10, 10));
            
            // Gets the number of detected pips and draws a cricle around the ROI
            for (int y = 0; y < pipDetections.toArray().length; y++) {
                // Provides the relative position of the pips to the dice ROI
                Rect pipRect = pipDetections.toArray()[y];
                
                // See syntax explaination
                // Draws a circle around our pips
                Point center = new Point(diceRect.x + pipRect.x + pipRect.width / 2,
                    diceRect.y + pipRect.y + pipRect.height / 2);
                Imgproc.ellipse(image, center, new Size(pipRect.width / 2, pipRect.height / 2),
                     0, 0, 360, new Scalar(255, 0, 255), 1, 0, 0);
            }
        }
        
        return image;
    }
}

getNextImage() 함수는 게시 된 다른 예제와 함께 Mat 객체를 반환합니다.이 객체는 지속적으로 호출 할 수 있으며 BufferImage 로 변환하여 탐지를 표시하는 실시간 스트리밍을 제공합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow