use of org.opencv.core.MatOfPoint in project kifu-recorder by leonardost.
the class RegistrarPartidaActivity method processarCantosDoTabuleiro.
private void processarCantosDoTabuleiro() {
posicaoDoTabuleiroNaImagem = new Mat(4, 1, CvType.CV_32FC2);
posicaoDoTabuleiroNaImagem.put(0, 0, cantosDoTabuleiro[0], cantosDoTabuleiro[1], cantosDoTabuleiro[2], cantosDoTabuleiro[3], cantosDoTabuleiro[4], cantosDoTabuleiro[5], cantosDoTabuleiro[6], cantosDoTabuleiro[7]);
Point[] cantos = new Point[4];
cantos[0] = new Point(cantosDoTabuleiro[0], cantosDoTabuleiro[1]);
cantos[1] = new Point(cantosDoTabuleiro[2], cantosDoTabuleiro[3]);
cantos[2] = new Point(cantosDoTabuleiro[4], cantosDoTabuleiro[5]);
cantos[3] = new Point(cantosDoTabuleiro[6], cantosDoTabuleiro[7]);
contornoDoTabuleiro = new MatOfPoint(cantos);
}
use of org.opencv.core.MatOfPoint in project kifu-recorder by leonardost.
the class DetectorDeTabuleiro method detectarTabuleiro.
private MatOfPoint detectarTabuleiro(List<MatOfPoint> quadrilateros) {
HierarquiaDeQuadrilateros hierarquiaDeQuadrilateros = new HierarquiaDeQuadrilateros(quadrilateros);
MatOfPoint contornoMaisProximoDoTabuleiro = null;
int numeroDeFilhos = 9999;
// Tem que ter pelo menos esse número de quadriláteros folha dentro
int threshold = 10;
for (MatOfPoint contorno : hierarquiaDeQuadrilateros.externos) {
if (hierarquiaDeQuadrilateros.hierarquia.get(contorno).size() < numeroDeFilhos && hierarquiaDeQuadrilateros.hierarquia.get(contorno).size() > threshold) {
contornoMaisProximoDoTabuleiro = contorno;
numeroDeFilhos = hierarquiaDeQuadrilateros.hierarquia.get(contorno).size();
}
}
return contornoMaisProximoDoTabuleiro;
}
use of org.opencv.core.MatOfPoint in project kifu-recorder by leonardost.
the class DetectorDeTabuleiro method detectarContornos.
private List<MatOfPoint> detectarContornos(Mat imagemComBordasEmEvidencia) {
// Os contornos delimitados pelas linhas são encontrados
List<MatOfPoint> contornos = new ArrayList<>();
Mat hierarquia = new Mat();
Imgproc.findContours(imagemComBordasEmEvidencia, contornos, hierarquia, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));
Log.d("kifu-recorder", "Número de contornos encontrados: " + contornos.size());
// Remove os contornos muito pequenos, que provavelmente são ruído
for (Iterator<MatOfPoint> it = contornos.iterator(); it.hasNext(); ) {
MatOfPoint contorno = it.next();
// O ideal seria fazer isto aqui como uma razão sobre a área da imagem
if (Imgproc.contourArea(contorno) < 700) {
it.remove();
}
}
// A imagem é convertida para um formato colorido novamente
Imgproc.cvtColor(imagemComBordasEmEvidencia, imagem, Imgproc.COLOR_GRAY2BGR, 4);
imagemComBordasEmEvidencia.release();
return contornos;
}
use of org.opencv.core.MatOfPoint in project kifu-recorder by leonardost.
the class DetectorDeTabuleiro method detectarQuadrilateros.
private List<MatOfPoint> detectarQuadrilateros(List<MatOfPoint> contornos) {
List<MatOfPoint> quadrilateros = new ArrayList<>();
for (MatOfPoint contorno : contornos) {
MatOfPoint2f contour2f = new MatOfPoint2f();
MatOfPoint2f approx2f = new MatOfPoint2f();
contorno.convertTo(contour2f, CvType.CV_32FC2);
// * 0.02 e * 0.03 também têm resultados interessantes
// Aparentemente, quanto maior o epsilon, mais curvas que não se encaixam perfeitamente nos contornos
// são consideradas. Contudo, esse parâmetro parece ser bastante sensível.
// Imgproc.approxPolyDP(contour2f, approx2f, Imgproc.arcLength(contour2f, true) * 0.04, true);
// Imgproc.approxPolyDP(contour2f, approx2f, Imgproc.arcLength(contour2f, true) * 0.008, true); // perde muitos quadrados
// Imgproc.approxPolyDP(contour2f, approx2f, Imgproc.arcLength(contour2f, true) * 0.01, true); // borda do tabuleiro encontrada bem, mas quadrados internos sofrem. Talvez seja melhor usar este por detectar melhor o quadrado externo
// Imgproc.approxPolyDP(contour2f, approx2f, Imgproc.arcLength(contour2f, true) * 0.015, true); // melhores resultados até agora
Imgproc.approxPolyDP(contour2f, approx2f, Imgproc.arcLength(contour2f, true) * 0.012, true);
// Imgproc.approxPolyDP(contour2f, approx2f, Imgproc.arcLength(contour2f, true) * 0.008, true);
MatOfPoint approx = new MatOfPoint();
approx2f.convertTo(approx, CvType.CV_32S);
double contourArea = Math.abs(Imgproc.contourArea(approx2f));
// Se tem 4 lados, é convexo e não é muito pequeno, é um quadrado válido
if (approx2f.toList().size() == 4 && contourArea > 400 && Imgproc.isContourConvex(approx)) {
quadrilateros.add(approx);
}
}
Log.d("kifu-recorder", "Número de quadriláteros encontrados: " + quadrilateros.size());
return quadrilateros;
}
use of org.opencv.core.MatOfPoint in project kifu-recorder by leonardost.
the class DetectorDeTabuleiro method processar.
/**
* Processa a imagem fornecida. Retorna verdadeiro se o processamento completo ocorreu com
* sucesso, ou seja, se um tabuleiro de Go foi detectado na imagem. Retorna falso, caso
* contrário.
*
* @return boolean
*/
public boolean processar() {
if (imagem == null) {
// lançar erro
return false;
}
Mat imagemComBordasEmEvidencia = detectarBordas();
// Se quiser ver a saída do detector de bordas Cammy
// Imgproc.cvtColor(imagemComBordasEmEvidencia, imagemDePreview, Imgproc.COLOR_GRAY2BGR, 4); if (true) return false;
// imagemDePreview = imagemComBordasEmEvidencia; if (true) return false;
List<MatOfPoint> contornos = detectarContornos(imagemComBordasEmEvidencia);
if (contornos.isEmpty()) {
Log.i(TestesActivity.TAG, "> Processamento de imagem: contornos não foram encontrados.");
return false;
}
// Se quiser ver a saída do detector de contornos
// Imgproc.drawContours(imagemDePreview, contornos, -1, new Scalar(0, 0, 255), 2); if (true) return false;
List<MatOfPoint> quadrilateros = detectarQuadrilateros(contornos);
if (quadrilateros.isEmpty()) {
Log.i(TestesActivity.TAG, "> Processamento de imagem: quadriláteros não foram encontrados.");
return false;
}
// Se quiser ver a saída do detector de quadriláteros
// for (MatOfPoint quadrilatero : quadrilateros) { List<MatOfPoint> listaContorno = new ArrayList<MatOfPoint>(); listaContorno.add(quadrilatero); Imgproc.drawContours(imagemDePreview, listaContorno, -1, new Scalar(255, 0, 0), 3); } if (true) return false;
MatOfPoint quadrilateroDoTabuleiro = detectarTabuleiro(quadrilateros);
if (quadrilateroDoTabuleiro == null) {
Log.i(TestesActivity.TAG, "> Processamento de imagem: quadrilátero do tabuleiro não foi encontrado.");
return false;
}
HierarquiaDeQuadrilateros hierarquiaDeQuadrilateros = new HierarquiaDeQuadrilateros(quadrilateros);
double areaMedia = 0;
for (MatOfPoint quadrilatero : hierarquiaDeQuadrilateros.hierarquia.get(quadrilateroDoTabuleiro)) {
areaMedia += Imgproc.contourArea(quadrilatero);
}
areaMedia /= hierarquiaDeQuadrilateros.hierarquia.get(quadrilateroDoTabuleiro).size();
double areaDoTabuleiro = Imgproc.contourArea(quadrilateroDoTabuleiro);
double razao = areaMedia / areaDoTabuleiro;
// com a área do quadrado do tabuleiro
if (razao <= 1.0 / 324.0) {
// 18 quadrados por 18
dimensaoDoTabuleiro = 19;
} else if (razao <= 1.0 / 144.0) {
// 12 quadrados por 12
dimensaoDoTabuleiro = 13;
} else {
dimensaoDoTabuleiro = 9;
}
List<Point> cantosDoTabuleiro = ordenarCantos(quadrilateroDoTabuleiro);
if (desenharPreview) {
// Desenhista.desenhaInterseccoesECantosDoTabuleiro(imagemDePreview, intersecoes, cantosDoTabuleiro);
Desenhista.desenharContornoDoTabuleiro(imagemDePreview, quadrilateroDoTabuleiro);
}
posicaoDoTabuleiroNaImagem = new Mat(4, 1, CvType.CV_32FC2);
posicaoDoTabuleiroNaImagem.put(0, 0, (int) cantosDoTabuleiro.get(0).x, (int) cantosDoTabuleiro.get(0).y, (int) cantosDoTabuleiro.get(1).x, (int) cantosDoTabuleiro.get(1).y, (int) cantosDoTabuleiro.get(2).x, (int) cantosDoTabuleiro.get(2).y, (int) cantosDoTabuleiro.get(3).x, (int) cantosDoTabuleiro.get(3).y);
/*
for (int i = 0; i < posicaoDoTabuleiroNaImagem.rows(); ++i) {
for (int j = 0; j < posicaoDoTabuleiroNaImagem.cols(); ++j) {
double[] valor = posicaoDoTabuleiroNaImagem.get(i, j);
Log.d(TestesActivity.TAG, "(" + i + ", " + j + ") = " + valor[0] + ", " + valor[1]);
}
}
*/
processadoComSucesso = true;
return true;
}
Aggregations