java - procesamiento - Detecta retratos rectangulares de personas en imágenes con OpenCV.
reconocimiento de imagenes python (1)
Tengo muchas imágenes de anuarios con retratos de personas y estoy tratando de construir un algoritmo que detecte esos retratos. Al menos, para detectar retratos rectangulares correctos. Ejemplo 1 Ejemplo 2
Estoy tratando de investigar tres direcciones:
- Detección de rostro
- Detección de rectángulos oscuros (ya que los retratos suelen ser formas más oscuras sobre un fondo más brillante)
- Nombres de personas extraídos de textos de OCR
Al combinar los resultados de los tres algoritmos anteriores, espero obtener alguna metodología, que será aplicable a muchas páginas de anuarios diferentes.
Agradecería cualquier ayuda para la detección de rectángulos. Comencé con Java y OpenCV 3.
Aquí está mi código aplicado para una imagen :
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat source = Imgcodecs.imread("Path/to/image", Imgcodecs.CV_LOAD_IMAGE_ANYCOLOR);
Mat destination = new Mat(source.rows(), source.cols(), source.type());
Imgproc.cvtColor(source, destination, Imgproc.COLOR_RGB2GRAY);
Imgproc.GaussianBlur(destination, destination, new Size(5, 5), 0, 0, Core.BORDER_DEFAULT);
int threshold = 100;
Imgproc.Canny(destination, destination, 50, 100);
Imgproc.Canny(destination, destination, threshold, threshold*3);
En este punto, tengo tal resultado:
Tratando de encontrar contornos desde los bordes de arriba:
List<MatOfPoint> contourDetections = new ArrayList<>();
Mat hierarchy = new Mat();
// Find contours
Imgproc.findContours(destination, contourDetections, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
// Draw contours
Imgproc.drawContours(source, contours, -1, new Scalar(255,0,0), 2);
Pero no estoy seguro de cómo extraer rectángulos de esos contornos ya que muchas de las líneas están incompletas.
Volviendo a los bordes y tratando de encontrar líneas verticales y horizontales usando HoughLinesP:
Mat lines = new Mat();
int thre = 50;
int minLineSize = 250;
int lineGap = 80;
int ignoreLinesShorter = 300;
Imgproc.HoughLinesP(destination, lines, 1, Math.PI/180, thre, minLineSize, lineGap);
for(int c = 0; c < lines.rows(); c++) {
double[] vec = lines.get(c, 0);
double x1 = vec[0],
y1 = vec[1],
x2 = vec[2],
y2 = vec[3];
// Filtering only verticat and horizontal lines
if(x1 == x2 || y1 == y2) {
// Filtering out short lines
if(Math.abs(x1 - x2) > ignoreLinesShorter || Math.abs(y1 - y2) > ignoreLinesShorter) {
Point start = new Point(x1, y1);
Point end = new Point(x2, y2);
// Draw line
Imgproc.line(source, start, end, new Scalar(0,0,255), 2);
}
}
}
Resultado:
Al igual que con los contornos, todavía no veo rectángulos correctos que pueda detectar. ¿Podrías ayudarme con una dirección correcta? Tal vez hay una forma más fácil de realizar esta tarea?
No es una respuesta completa pero puede ser útil.
Obtengo la imagen de abajo con el siguiente código.
para entender el código, puede consultar mi respuesta anterior en http://answers.opencv.org/question/85884
Si parece prometedor intentaremos mejorarlo juntos.
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
using namespace cv;
int main(int argc, char** argv)
{
Mat img = imread("e:/test/twHVm.jpg");
if (img.empty())
return -1;
Mat resized, gray, reduced_h, reduced_w;
resize(img, resized, Size(), 1, 1);
cvtColor(resized, gray, CV_BGR2GRAY);
reduce(gray, reduced_h, 0, REDUCE_AVG);
reduce(gray, reduced_w, 1, REDUCE_AVG);
for (int i = 0; i < img.cols; i++)
{
if (reduced_h.at<uchar>(0, i) > 200) // this is experimental value
line(resized, Point(i, 0), Point(i, img.rows), Scalar(0, 255, 0), 1);
}
for (int i = 0; i < img.rows; i++)
{
if (reduced_w.at<uchar>(i, 0) > 225) // this is experimental value
line(resized, Point(0, i), Point(img.cols, i), Scalar(0, 255, 0), 1);
}
imshow("result", resized);
waitKey(0);
return 0;
}