【发布时间】:2019-05-10 02:44:21
【问题描述】:
我正在做一个项目,我必须在 Java 中使用 openCV 来识别井字游戏板的状态。请看下面的示例程序执行。
输入
输出
X,-,-
-,O,-
X,-,-
我试图通过在图像中查找轮廓来解决这个问题,但问题是空的未标记框也被捕获,我无法使用多边形大小和轮廓等轮廓属性来区分形状区域。以下是我目前的代码。
package finalproject;
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfInt;
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.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class FinalProject {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat image = Imgcodecs.imread("C://Users//BadarJahan//Desktop//board-
perfect.jpg");
Mat binaryImage = preprocess(image);
List<MatOfPoint> contours = new ArrayList<>();
Imgproc.findContours(binaryImage, contours,new Mat() ,Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_SIMPLE);
List<MatOfPoint2f> contoursConvert = new ArrayList<>();
for(MatOfPoint contour : contours) {
contoursConvert.add(new MatOfPoint2f(contour.toArray()));
}
identifyTicTacToeConfiguration(binaryImage,contoursConvert);
}
private static Mat preprocess(Mat colorImage) {
// Imgproc.resize(colorImage, colorImage, new Size(489,0));
Mat grayImage = new Mat() , binaryImage = new Mat();
Imgproc.cvtColor(colorImage, grayImage,Imgproc.COLOR_BGR2GRAY);
binaryImage = grayImage;
Imgproc.threshold(grayImage, binaryImage, 0, 255, Imgproc.THRESH_BINARY_INV | Imgproc.THRESH_OTSU);
final Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5,5));
Imgproc.morphologyEx(binaryImage, binaryImage, Imgproc.MORPH_CLOSE, kernel);
return binaryImage;
}
private static MatOfPoint2f getApproxPoly(final MatOfPoint2f contour) {
MatOfPoint2f polyContour = new MatOfPoint2f();
final double epsillon = Imgproc.arcLength(contour, true) * 0.02;
final boolean close = true;
Imgproc.approxPolyDP(contour, polyContour, epsillon, close);
return polyContour;
}
private static void printContourProperties(final MatOfPoint contour) {
final double contourArea = Imgproc.contourArea(contour);
MatOfInt convexHull = new MatOfInt();
Imgproc.convexHull(contour, convexHull);
// final double convexHullArea = Imgproc.contourArea(convexHull);
Rect boundingRect = Imgproc.boundingRect(contour);
MatOfPoint2f poly = getApproxPoly(new
MatOfPoint2f(contour.toArray()));
System.out.println("Contour area : " + contourArea);
System.out.println("Aespect Ratio : " +
boundingRect.width/boundingRect.height);
System.out.println("Extend: " + contourArea/boundingRect.area());
// System.out.println("Solidity : " + contourArea/convexHullArea);
System.out.println("Poly Size : " + poly.size().area() + ", is
convex " + Imgproc.isContourConvex(new MatOfPoint(poly.toArray())));
System.out.println();
}
private static void showContourProperties(final Mat input, final List<MatOfPoint> contours) {
Mat inputCopy = new Mat();
for(int i = 0; i < contours.size(); i++) {
input.copyTo(inputCopy);
Scalar color = new Scalar(255);
final int thickness = 3;
Imgproc.drawContours(inputCopy, contours, i, color,thickness);
printContourProperties(contours.get(i));
Imgcodecs.imwrite("C://Users//BadarJahan//Desktop//Test-1-check-
"+i+".jpg", inputCopy);
}
}
private static ContourType recognizeContourType(final MatOfPoint2f contour) {
final double contourArea = Imgproc.contourArea(contour);
final MatOfPoint2f poly = getApproxPoly(contour);
ContourType type = ContourType.Unknown;
if((poly.elemSize() > 7 && poly.elemSize() < 10) && contourArea < 1000) {
type = ContourType.OType;
}else if(contourArea > 10000) {
type = ContourType.XType;
}
return type;
}
private static void identifyTicTacToeConfiguration(final Mat input, final List<MatOfPoint2f> contours) {
for(MatOfPoint2f contour: contours) {
ContourType type = recognizeContourType(contour);
if(type == ContourType.XType) {
System.out.print("X");
}else if(type == ContourType.OType) {
System.out.print("O");
}
}
}
}
任何帮助将不胜感激。谢谢
【问题讨论】:
-
裁剪九个单元格后,您可以做 1- 每个框的阈值,2- 填充孔并找到区域的填充区域,3- 如果没有区域,则将其分类为空,如果区域最小则为 x阈值,如果面积大于阈值,则为 O。
-
@user8190410 如何在代码中将图像裁剪为 3 x 3 网格?
-
如果您在 3x3 网格中固定了框尺寸:假设您的窗口等于 150x150,并且有 9 个 50x50 尺寸的框。第一个盒子是
box1 = window[0:50,0:50]然后第二个盒子是box2 = window[0:50,50:100]等等
标签: java opencv image-processing opencv3.0 tic-tac-toe