OpenCV - 删除错误的轮廓
OpenCV - Remove wrong contours
我有一个关于 OpenCV 和查找特定形状的简短问题。在我的电脑上,我有一张带有一些形状的图片,但我只想要矩形的轮廓:
输入文件:
我的输出应该是:
我的实际输出是:
我做了什么:
- 打开我的图像并将其转换为 OpenCV Mat。
- 进行了一些图像处理[灰度、模糊]
- 使用 Canny 找到边
- 找到 "findContours"
的等高线
- 用 "boundingRect"
围绕我的轮廓画矩形
这就是我卡住的地方。我不知道如何消除错误的轮廓。我尝试迭代我的轮廓并删除不正确的轮廓。但我不知道如何找到错误的轮廓。有没有我必须使用的公式或某事。像这样?我用 "arcLength" 找到了一些东西,但我不明白这一点。
这是我的代码:
package main;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import helper.ImageProcHelper;
public class Main {
public static void main(String[] args) throws Exception {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
File file = new File("C:\Users\Enrico Gründig\Desktop\Samples\pic4.png");
Mat mat = new Mat(CvType.CV_8UC4);
Mat procMat = new Mat();
Mat hierarchy = new Mat();
Scalar color = new Scalar(0,0,255);
List<MatOfPoint> contours = new ArrayList<>();
try {
BufferedImage picture = ImageIO.read(file);
BufferedImage image = new BufferedImage(picture.getWidth(), picture.getHeight(), 5);
image.getGraphics().drawImage(picture, 0, 0, null);
System.out.println(image.getType());
mat = ImageProcHelper.ImageToMat(image);
Imgproc.cvtColor(mat, procMat, Imgproc.COLOR_RGBA2GRAY);
Imgproc.blur(procMat, procMat, new Size(3,3));
Imgproc.Canny(procMat, procMat, 127, 255);
//Konturen finden
Imgproc.findContours(procMat, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
MatOfPoint2f[] contoursPoly = new MatOfPoint2f[contours.size()];
Rect[] boundRect = new Rect[contours.size()];
for(int i = 0; i < contours.size(); i++) {
contoursPoly[i] = new MatOfPoint2f();
Imgproc.approxPolyDP(new MatOfPoint2f(contours.get(i).toArray()), contoursPoly[i], 0.1, true);
boundRect[i] = Imgproc.boundingRect(new MatOfPoint(contours.get(i).toArray()));
}
for (int i = 0; i < contours.size(); i++) {
Imgproc.rectangle(mat, boundRect[i].tl(), boundRect[i].br(), color, 1);
}
image = ImageProcHelper.MatToImage(mat);
ImageIO.write((RenderedImage)image, "png", new File ("C:\Users\Enrico Gründig\Desktop\Samples\output.png"));
} catch (IOException e) {
System.out.println("Error");
}
}
}
这个项目的重点是什么:
我有一个正在播放视频的网络摄像机。在这个项目中,我想找到流中的所有 QR 码,裁剪它们并将它们传递给解码器(例如 ZXing)。我只用 ZXing 尝试过,但我在角度、大小等方面遇到了问题。这就是为什么我想使用 OpenCV 来查找代码并操纵它们以减少从 IP 摄像机到解码器的流量并(可能)提高命中率。
二维码示例:
这应该是我的输出:
这是我的输出:
非常感谢您的帮助。
我没有足够的声誉来评论,但你似乎缺少的是检查每个轮廓的边。在您的代码中,您需要使用 contoursPoly[i].size() 来区分不同的形状。您的代码最终需要看起来像这样:
package main;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import helper.ImageProcHelper;
public class Main {
public static void main(String[] args) throws Exception {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
File file = new File("C:\Users\Enrico Gründig\Desktop\Samples\pic4.png");
Mat mat = new Mat(CvType.CV_8UC4);
Mat procMat = new Mat();
Mat hierarchy = new Mat();
Scalar color = new Scalar(0,0,255);
List<MatOfPoint> contours = new ArrayList<>();
try {
BufferedImage picture = ImageIO.read(file);
BufferedImage image = new BufferedImage(picture.getWidth(), picture.getHeight(), 5);
image.getGraphics().drawImage(picture, 0, 0, null);
System.out.println(image.getType());
mat = ImageProcHelper.ImageToMat(image);
Imgproc.cvtColor(mat, procMat, Imgproc.COLOR_RGBA2GRAY);
Imgproc.blur(procMat, procMat, new Size(3,3));
Imgproc.Canny(procMat, procMat, 127, 255);
//Konturen finden
Imgproc.findContours(procMat, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
MatOfPoint2f[] contoursPoly = new MatOfPoint2f[contours.size()];
Rect[] boundRect = new Rect[contours.size()];
for(int i = 0; i < contours.size(); i++) {
contoursPoly[i] = new MatOfPoint2f();
Imgproc.approxPolyDP(new MatOfPoint2f(contours.get(i).toArray()), contoursPoly[i], 0.1, true);
boundRect[i] = Imgproc.boundingRect(new MatOfPoint(contours.get(i).toArray()));
}
for (int i = 0; i < contours.size(); i++) {
if (contoursPoly[i].size()>15){
Imgproc.rectangle(mat, boundRect[i].tl(), boundRect[i].br(), color, 1);
}
}
image = ImageProcHelper.MatToImage(mat);
ImageIO.write((RenderedImage)image, "png", new File ("C:\Users\Enrico Gründig\Desktop\Samples\output.png"));
} catch (IOException e) {
System.out.println("Error");
}
}
}
我没有 Java OpenCV 设置,所以我无法测试这段代码,但我的想法来自这个 link。您可能不得不乱用“15”来区分矩形和圆形。
我有一个关于 OpenCV 和查找特定形状的简短问题。在我的电脑上,我有一张带有一些形状的图片,但我只想要矩形的轮廓:
输入文件:
我的输出应该是:
我的实际输出是:
我做了什么:
- 打开我的图像并将其转换为 OpenCV Mat。
- 进行了一些图像处理[灰度、模糊]
- 使用 Canny 找到边
- 找到 "findContours" 的等高线
- 用 "boundingRect" 围绕我的轮廓画矩形
这就是我卡住的地方。我不知道如何消除错误的轮廓。我尝试迭代我的轮廓并删除不正确的轮廓。但我不知道如何找到错误的轮廓。有没有我必须使用的公式或某事。像这样?我用 "arcLength" 找到了一些东西,但我不明白这一点。
这是我的代码:
package main;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import helper.ImageProcHelper;
public class Main {
public static void main(String[] args) throws Exception {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
File file = new File("C:\Users\Enrico Gründig\Desktop\Samples\pic4.png");
Mat mat = new Mat(CvType.CV_8UC4);
Mat procMat = new Mat();
Mat hierarchy = new Mat();
Scalar color = new Scalar(0,0,255);
List<MatOfPoint> contours = new ArrayList<>();
try {
BufferedImage picture = ImageIO.read(file);
BufferedImage image = new BufferedImage(picture.getWidth(), picture.getHeight(), 5);
image.getGraphics().drawImage(picture, 0, 0, null);
System.out.println(image.getType());
mat = ImageProcHelper.ImageToMat(image);
Imgproc.cvtColor(mat, procMat, Imgproc.COLOR_RGBA2GRAY);
Imgproc.blur(procMat, procMat, new Size(3,3));
Imgproc.Canny(procMat, procMat, 127, 255);
//Konturen finden
Imgproc.findContours(procMat, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
MatOfPoint2f[] contoursPoly = new MatOfPoint2f[contours.size()];
Rect[] boundRect = new Rect[contours.size()];
for(int i = 0; i < contours.size(); i++) {
contoursPoly[i] = new MatOfPoint2f();
Imgproc.approxPolyDP(new MatOfPoint2f(contours.get(i).toArray()), contoursPoly[i], 0.1, true);
boundRect[i] = Imgproc.boundingRect(new MatOfPoint(contours.get(i).toArray()));
}
for (int i = 0; i < contours.size(); i++) {
Imgproc.rectangle(mat, boundRect[i].tl(), boundRect[i].br(), color, 1);
}
image = ImageProcHelper.MatToImage(mat);
ImageIO.write((RenderedImage)image, "png", new File ("C:\Users\Enrico Gründig\Desktop\Samples\output.png"));
} catch (IOException e) {
System.out.println("Error");
}
}
}
这个项目的重点是什么:
我有一个正在播放视频的网络摄像机。在这个项目中,我想找到流中的所有 QR 码,裁剪它们并将它们传递给解码器(例如 ZXing)。我只用 ZXing 尝试过,但我在角度、大小等方面遇到了问题。这就是为什么我想使用 OpenCV 来查找代码并操纵它们以减少从 IP 摄像机到解码器的流量并(可能)提高命中率。
二维码示例:
这应该是我的输出:
这是我的输出:
非常感谢您的帮助。
我没有足够的声誉来评论,但你似乎缺少的是检查每个轮廓的边。在您的代码中,您需要使用 contoursPoly[i].size() 来区分不同的形状。您的代码最终需要看起来像这样:
package main;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import helper.ImageProcHelper;
public class Main {
public static void main(String[] args) throws Exception {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
File file = new File("C:\Users\Enrico Gründig\Desktop\Samples\pic4.png");
Mat mat = new Mat(CvType.CV_8UC4);
Mat procMat = new Mat();
Mat hierarchy = new Mat();
Scalar color = new Scalar(0,0,255);
List<MatOfPoint> contours = new ArrayList<>();
try {
BufferedImage picture = ImageIO.read(file);
BufferedImage image = new BufferedImage(picture.getWidth(), picture.getHeight(), 5);
image.getGraphics().drawImage(picture, 0, 0, null);
System.out.println(image.getType());
mat = ImageProcHelper.ImageToMat(image);
Imgproc.cvtColor(mat, procMat, Imgproc.COLOR_RGBA2GRAY);
Imgproc.blur(procMat, procMat, new Size(3,3));
Imgproc.Canny(procMat, procMat, 127, 255);
//Konturen finden
Imgproc.findContours(procMat, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
MatOfPoint2f[] contoursPoly = new MatOfPoint2f[contours.size()];
Rect[] boundRect = new Rect[contours.size()];
for(int i = 0; i < contours.size(); i++) {
contoursPoly[i] = new MatOfPoint2f();
Imgproc.approxPolyDP(new MatOfPoint2f(contours.get(i).toArray()), contoursPoly[i], 0.1, true);
boundRect[i] = Imgproc.boundingRect(new MatOfPoint(contours.get(i).toArray()));
}
for (int i = 0; i < contours.size(); i++) {
if (contoursPoly[i].size()>15){
Imgproc.rectangle(mat, boundRect[i].tl(), boundRect[i].br(), color, 1);
}
}
image = ImageProcHelper.MatToImage(mat);
ImageIO.write((RenderedImage)image, "png", new File ("C:\Users\Enrico Gründig\Desktop\Samples\output.png"));
} catch (IOException e) {
System.out.println("Error");
}
}
}
我没有 Java OpenCV 设置,所以我无法测试这段代码,但我的想法来自这个 link。您可能不得不乱用“15”来区分矩形和圆形。