Я не уверен, если это то, что вы ищете (особенно, так как это в Java), но проверить this file, в частности, функция в строке 121.
Вот это для вашего удобства:
MatOfRect diceDetections = new MatOfRect(); // Essentially an array of locations where our dice features were detected. (Stupid wrappers)
// Note that detectMultiScale has thrown an unknown exception before (literally, unknown). This is to prevent crashing.
try {
diceCascade.detectMultiScale(image, diceDetections, 1.1, 4, 0, new Size(20, 20), new Size(38, 38));
} catch (Exception e) {
e.printStackTrace();
}
// Debug, used for console output
String curDetect = "";
// 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();
try {
/*
* Now this is interesting. We essentially create a sub-array of the image, with our dice ROI as the image. Then we perform the detection on the image. This gives us the relative
* positions of our pip ROIs to the dice ROI. Later on, we can draw the circles around the pip ROI, with the centers' positions adjusted by adding the dice ROI positions, so that it
* renders properly. This is an amazing trick, as it not only eliminates false positives in non-dice ROIs, but it reduces how many pixels the classifier has to analyze to only at most
* 38 x 38 pixels (because of the size restraints provided while detecting dice ROIs). This means we can set the precision to an insane level, without performance loss.
*/
pipCascade.detectMultiScale(image.submat(diceRect), pipDetections, 1.01, 4, 0, new Size(2, 2), new Size(10, 10));
} catch (Exception e) {
e.printStackTrace();
}
// Gets the number of detected pips and draws a cricle around the ROI
int numPips = 0;
for (int y = 0; y < pipDetections.toArray().length; y++) {
Rect pipRect = pipDetections.toArray()[y]; // Provides the relative position of the pips to the dice ROI
/*
* Finds the absolute center of a pip. diceRect.x and diceRect.y provides the top-left position of the dice ROI. pipRect.x and pipRect.y provides the top-left position of the pip ROI.
* Normally, to find a center of an object with size (w, h) with the top-left point (x, y), we divide the width and height by two, and then add on the x pos to the width and y pos to
* the height. Now, since pipDetections only provide relative positioning to the dice ROI, we also need to add the dice position to find our absolute center position (aka relative to
* the entire image).
*/
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);
numPips++;
}
в общем, у меня есть два классификаторы, один признать DICE (строка 129) и один признать зернышки (черные точки) на кости. Он получает массив ROI для костей, а затем для каждого элемента в массиве, возьмите подматрицу изображения (расположенную в ROI) и попросите классификатор пинга по этой матрице вместо всего изображения (строка 156). Однако, если вы пытаетесь отобразить обнаружение (пипсы в моем примере), вам нужно будет компенсировать его положением ROI, в котором вы находитесь, следовательно, работа по линиям 171 и 172.
Я уверен, что это обеспечивает тот же выигрыш в производительности, который вы ищете, просто не обязательно одним и тем же способом (subimaging vs masking).
Это именно то, что я искал. Для меня не важно, нужно ли использовать маски или субимазы, чтобы получить прирост производительности, но в первую очередь я подумал, что OpenCV уже реализовал что-то вроде субимации внутри детекторов функций. –