【发布时间】:2018-09-03 21:43:51
【问题描述】:
我有一张黑白图像(单通道,仅限 0 和 255),我想使用 Java 中的 openCV 3.4.2 删除其中低于某个区域阈值的小斑点。
现在我已经找到了以下线程:Removing blobs from a binary image,几乎相同 - 但我需要一些帮助将答案翻译成 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 个图像。
示例输出(去除所有轮廓后的最后一张图像):
【问题讨论】:
-
请把它变成一个独立的 MCVE,只编译,并添加一些示例输入/输出图像。 |
drawContours只是吸引到您提供的Mat中——它不会改变频道数。 -
作为获得更多线索的一种方式,将
drawContours移动到for循环中,让它一次绘制一个轮廓到空白图像中,并使用 HighGUI 将其可视化(或者只是将图像保存到磁盘)。 -
感谢您的反馈,我将在今天晚些时候回到家时进行这些更改,然后提供更新
-
您好,我将代码转换为 MCVE 并添加了示例输入/输出。
-
啊,
contours.remove(i);在迭代contours的循环中。你增加索引,即使你删除,所以你最终会跳过一些条目。不要从原始轮廓数组中删除不受欢迎的那些,而是将所需的那些添加到新的ArrayList中,然后绘制它。
标签: java opencv image-processing