检测中的检测
这个例子使用 Dice 和骰子上的黑点(点子)作为我们的对象。由于示例很长,首先解释一些关键概念对于理解示例至关重要。
理解第一个示例“获取静态图像,检测其中的项目,然后输出结果”。对于理解这个例子至关重要,特别是 OpenCV 如何绘制矩形。
看一下下图:
我们将使用子成像方法,我们使用检测到的区域作为应用更多检测的基础。只有当一个对象永远位于我们可以检测到的另一个对象中时,例如我们骰子上的点数,这才有可能。这种方法有几个好处:
- 在扫描整个图像时,我们只需要扫描我们知道对象所在的区域。
- 消除检测区域外任何误报的可能性。
我们首先在整个图像上应用一个级联分类器扫描,为我们提供一个包含我们大对象的 MatOfRect
对象(在本例中为骰子)。然后我们迭代 toArray()
对象给出的 toArray()
对象提供的 Rect[]
数组。此 Rect
对象用于创建临时 Mat
对象,该对象从原始图像裁剪到 Rect
对象的属性(x, y, width, height
),然后我们可以在临时 Mat
对象上执行检测。换句话说,我们告诉分类器仅对图像的骰子部分执行检测,并且我们通过使用从对整个图像执行检测获得的 Rect
对象来指定每个骰子的位置。
然而,Rect
对象(点子)具有相对于其骰子的属性,而不是图像本身。为了解决这个问题,当我们想要将矩形绘制到显示点位置的实际图像时,我们将 dice.x
和 dice.y
添加到 start 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
,以提供显示检测的直播。