J'ai utilisé une méthode basée sur le gradient dans le programme ci-dessous. Ajouté les images résultantes. Veuillez noter que j'utilise une version réduite de l'image pour le traitement.
Version c++
La licence MIT (MIT)
Copyright (c) 2014 Dhanushka Dangampola
La permission est accordée, gratuitement, à toute personne obtenant une copie
de ce logiciel et des fichiers de documentation associés (le "Logiciel"), de traiter
dans le Logiciel sans restriction, y compris, sans limitation, les droits
d'utiliser, copier, modifier, fusionner, publier, distribuer, concéder sous licence et/ou vendre
des copies du Logiciel, et de permettre aux personnes à qui le Logiciel est
fourni de le faire, sous réserve des conditions suivantes :
L'avis de droit d'auteur ci-dessus et cet avis de permission doivent être inclus dans
toutes les copies ou des parties substantielles du Logiciel.
LE LOGICIEL EST FOURNI "TEL QUEL", SANS GARANTIE D'AUCUNE SORTE, EXPRESSE OU
IMPLICITE, Y COMPRIS, MAIS SANS S'Y LIMITER AUX GARANTIES DE COMMERCIALISATION,
D'ADEQUATION A UN USAGE PARTICULIER ET D'ABSENCE DE CONTREFACON. EN AUCUN CAS LES
AUTEURS OU DETENTEURS DU DROIT D'AUTEUR NE PEUVENT ÊTRE TENU RESPONSABLES DE TOUTE RÉCLAMATION, DOMMAGES OU AUTRES
RESPONSABILITÉ, QUE CE SOIT DANS UNE ACTION CONTRACTUELLE, TORT OU AUTRE, DÉCOULANT DE,
HORS DE OU EN LIEN AVEC LE LOGICIEL OU L'UTILISATION OU AUTRES ACCORDS DANS
LE LOGICIEL.
#include "stdafx.h"
#include
#include
#include
#include
using namespace cv;
using namespace std;
#define INPUT_FILE "1.jpg"
#define OUTPUT_FOLDER_PATH string("")
int _tmain(int argc, _TCHAR* argv[])
{
Mat large = imread(INPUT_FILE);
Mat rgb;
// downsample and use it for processing
pyrDown(large, rgb);
Mat small;
cvtColor(rgb, small, CV_BGR2GRAY);
// morphological gradient
Mat grad;
Mat morphKernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
morphologyEx(small, grad, MORPH_GRADIENT, morphKernel);
// binarize
Mat bw;
threshold(grad, bw, 0.0, 255.0, THRESH_BINARY | THRESH_OTSU);
// connect horizontally oriented regions
Mat connected;
morphKernel = getStructuringElement(MORPH_RECT, Size(9, 1));
morphologyEx(bw, connected, MORPH_CLOSE, morphKernel);
// find contours
Mat mask = Mat::zeros(bw.size(), CV_8UC1);
vector> contours;
vector hierarchy;
findContours(connected, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// filter contours
for(int idx = 0; idx >= 0; idx = hierarchy[idx][0])
{
Rect rect = boundingRect(contours[idx]);
Mat maskROI(mask, rect);
maskROI = Scalar(0, 0, 0);
// fill the contour
drawContours(mask, contours, idx, Scalar(255, 255, 255), CV_FILLED);
// ratio of non-zero pixels in the filled region
double r = (double)countNonZero(maskROI)/(rect.width*rect.height);
if (r > .45 /* assume at least 45% of the area is filled if it contains text */
&&
(rect.height > 8 && rect.width > 8) /* constraints on region size */
/* these two conditions alone are not very robust. better to use something
like the number of significant peaks in a horizontal projection as a third condition */
)
{
rectangle(rgb, rect, Scalar(0, 255, 0), 2);
}
}
imwrite(OUTPUT_FOLDER_PATH + string("rgb.jpg"), rgb);
return 0;
}
Version python
La licence MIT (MIT)
Copyright (c) 2017 Dhanushka Dangampola
La permission est accordée, gratuitement, à toute personne obtenant une copie
de ce logiciel et des fichiers de documentation associés (le "Logiciel"), de traiter
dans le Logiciel sans restriction, y compris, sans limitation, les droits
d'utiliser, copier, modifier, fusionner, publier, distribuer, concéder sous licence et/ou vendre
des copies du Logiciel, et de permettre aux personnes à qui le Logiciel est
fourni de le faire, sous réserve des conditions suivantes :
L'avis de droit d'auteur ci-dessus et cet avis de permission doivent être inclus dans
toutes les copies ou des parties substantielles du Logiciel.
LE LOGICIEL EST FOURNI "TEL QUEL", SANS GARANTIE D'AUCUNE SORTE, EXPRESSE OU
IMPLICITE, Y COMPRIS, MAIS SANS S'Y LIMITER AUX GARANTIES DE COMMERCIALISATION,
D'ADEQUATION A UN USAGE PARTICULIER ET D'ABSENCE DE CONTREFACON. EN AUCUN CAS LES
AUTEURS OU DETENTEURS DU DROIT D'AUTEUR NE PEUVENT ÊTRE TENU RESPONSABLES DE TOUTE RÉCLAMATION, DOMMAGES OU AUTRES
RESPONSABILITÉ, QUE CE SOIT DANS UNE ACTION CONTRACTUELLE, TORT OU AUTRE, DÉCOULANT DE,
HORS DE OU EN LIEN AVEC LE LOGICIEL OU L'UTILISATION OU AUTRES ACCORDS DANS
LE LOGICIEL.
import cv2
import numpy as np
large = cv2.imread('1.jpg')
rgb = cv2.pyrDown(large)
small = cv2.cvtColor(rgb, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
grad = cv2.morphologyEx(small, cv2.MORPH_GRADIENT, kernel)
_, bw = cv2.threshold(grad, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))
connected = cv2.morphologyEx(bw, cv2.MORPH_CLOSE, kernel)
# en utilisant RETR_EXTERNAL au lieu de RETR_CCOMP
contours, hierarchy = cv2.findContours(connected.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
#Pour opencv 3+ commenter la ligne précédente et décommenter la ligne suivante
#_, contours, hierarchy = cv2.findContours(connected.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
mask = np.zeros(bw.shape, dtype=np.uint8)
for idx in range(len(contours)):
x, y, w, h = cv2.boundingRect(contours[idx])
mask[y:y+h, x:x+w] = 0
cv2.drawContours(mask, contours, idx, (255, 255, 255), -1)
r = float(cv2.countNonZero(mask[y:y+h, x:x+w])) / (w * h)
if r > 0.45 and w > 8 and h > 8:
cv2.rectangle(rgb, (x, y), (x+w-1, y+h-1), (0, 255, 0), 2)
cv2.imshow('rects', rgb)
1 votes
La façon la plus simple que je vois ici est d'augmenter le contraste avant d'obtenir les régions...
3 votes
Cool question. Merci de l'avoir posée et d'avoir posté la prime pour garantir ces réponses intéressantes.
0 votes
Nouveau dans la programmation. Est-ce que la même chose peut être faite pour le texte dans des scripts autres que l'anglais comme le sanskrit?