[英]openCV Java | Remove blobs by area in a binary image
我有一个黑白图像(单通道,0和255只),我想在Java中使用openCV 3.4.2删除低于某个区域阈值的小blob。
现在我已经找到了以下线程: 从二进制映像中删除blob ,这几乎是一样的 - 但我需要一些帮助将答案转换为Java代码。 此外,由于我想删除黑点,我在处理前后反转图像。 编辑:感谢一些建议,我设法得到一个工作代码并修改它,所以现在它是一个MCVE。
我到目前为止的尝试:
import java.util.ArrayList;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class contourCheck {
public static void main(String[] args) {
// initialises openCV
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// reads original black&white image
Mat binary_image = Imgcodecs.imread("C:/Users/MyName/Desktop/TestImages/testpic.png", Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
// creates temporary Mat
Mat temp_image = binary_image;
// inverts image
Core.bitwise_not(temp_image,temp_image);
// finds all contours in the image
ArrayList<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(temp_image, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_NONE);
// deletes contours above minArea to keep only the contours that are supposed to be removed from the image
int minArea = 10;
for (int i = 0; i < contours.size(); i++) {
double area = Imgproc.contourArea(contours.get(i));
if (area > minArea) {
contours.remove(i);
}
}
System.out.println("number of contours remaining: " + contours.size());
for (int j = 0; j < contours.size(); j++) {
if (j > 0) { // apparently temp_image gets also inverted, therefore it gets inverted here once again
Core.bitwise_not(temp_image,temp_image);
}
// fills in small (<= minArea) contours with 0's
Imgproc.drawContours(temp_image, contours,j, new Scalar(0),Core.FILLED);
// inverts image once again to get the original state
Core.bitwise_not(temp_image,binary_image);
// writes image with filtered contours
Imgcodecs.imwrite("C:/Users/MyName/Desktop/TestImages/test/testpic_filtered" + j + ".png", binary_image);
}
}
}
现在这是一个示例图片,我想删除minArea
(= 10)以下的所有黑点:
我现在感到惊讶的是,一些非常大的组件被移除(例如,内部有一些小圆圈的巨大圆圈或巨大的矩形),而较小的组件被保留。 我的代码中是否有错误,或者我在这里误解了一些概念? 另外,为什么bitwise_not还会反转temp_image
,源Mat( Core.bitwise_not(temp_image,binary_image)
)?
注意:代码为每个被删除的轮廓创建一个图像,这意味着创建了74个图像。
示例输出(删除所有轮廓后的最后一个图像):
问题出在以下循环中:
for (int i = 0; i < contours.size(); i++) {
double area = Imgproc.contourArea(contours.get(i));
if (area > minArea) {
contours.remove(i);
}
}
请注意,您迭代contours
,同时有时会remove
元素。 请记住, remove
会将所有后续元素向前移动一个位置。 现在,您在每次迭代时递增索引。 这将导致您跳过每个已删除的轮廓。 由于你目前的目标只是保留足够小的轮廓,效果是一些较大的轮廓会滑过。
我解决这个问题的建议是采用稍微不同的方法 - 而不是删除不想要的轮廓,我创建一个新的ArrayList<MatOfPoint>
实例,并用我感兴趣的轮廓填充它并使用它在进一步处理中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.