[PYTHON] J'ai essayé d'extraire des caractères des sous-titres (OpenCV: édition tesseract-ocr)

introduction

Ici, je vais essayer d'extraire des caractères des sous-titres affichés sous Masami Broadcasting. Puisqu'il n'y a pas de fond, il semble tout à fait ainsi avec la binarisation.

Il est possible d'obtenir le personnage et la position avec une précision considérable en extrayant le personnage avec l'API google cloud vision, mais ici, je vais essayer d'obtenir le personnage par d'autres méthodes.

tesseract-ocr / pyocr

Tout d'abord, essayez la reconnaissance de caractères en utilisant tesseract et pyocr.

Ceci est l'image source. sentences.png

Extrayez les personnages et les positions avec le script ci-dessous.

import sys

import pyocr
import pyocr.builders

import cv2
from PIL import Image

def imageToText(src):
	tools = pyocr.get_available_tools()
	if len(tools) == 0:
		print("No OCR tool found")
		sys.exit(1)

	tool = tools[0]

	dst = tool.image_to_string(
		Image.open(src),
		lang='jpn',
		builder=pyocr.builders.WordBoxBuilder(tesseract_layout=6)
	)
	return dst	

if __name__ == '__main__':
	img_path = sys.argv[1]

	out = imageToText(img_path)

	img = cv2.imread(img_path)
	sentence = []
	for d in out:
		sentence.append(d.content)
		cv2.rectangle(img, d.position[0], d.position[1], (0, 0, 255), 2)

	print("".join(sentence).replace("。","。\n"))

	cv2.imshow("img", img)
	cv2.imwrite("output.png ", img)
	cv2.waitKey(0)
	cv2.destroyAllWindows()

Article 25 Tous les citoyens ont le droit de mener une vie saine et culturellement minimale.
Les deux pays doivent s’efforcer d’améliorer et de promouvoir la protection sociale, la sécurité sociale et la santé publique dans tous les aspects de la vie.
(Droit de recevoir une éducation et procédure pour recevoir]Article 26 Tous les citoyens ont le droit de recevoir une éducation égale en fonction de leurs capacités, conformément à la loi.
2 Tous les citoyens sont tenus de faire suivre à leurs enfants une éducation ordinaire, comme l'exige la loi.
L'enseignement obligatoire est gratuit.
[Droits et obligations du travail, normes des conditions de travail et interdiction de la maltraitance des enfants] Article 27 Tous les citoyens ont le droit et l'obligation de travailler.
2 Les normes relatives aux salaires, aux heures de travail, au repos et aux autres conditions de travail sont fixées par la loi.
3 Les enfants ne doivent pas l'utiliser.
Droit des travailleurs d'organisation et d'action de groupe] Article 28 Le droit d'union des travailleurs et le droit de négociation de groupe et d'autres actions de groupe sont garantis.
Droits de propriété] Article 29 Les droits de propriété ne sont pas violés.
2 Le contenu des droits de propriété est stipulé par la loi de manière à être conforme au bien-être public.
3 La propriété privée peut être utilisée pour le public moyennant une juste compensation.

Dans l'image des seuls caractères obtenus à partir de word ou html, les caractères eux-mêmes peuvent être obtenus, mais la position exacte des caractères semble difficile à obtenir. Ce que je veux ici, c'est la position en unités de phrase, mais même si je l'ajuste avec le paramètre tesseract_layout = 6, il semble que je ne puisse l'obtenir qu'en unités de caractères.

Méthode

output.png

range.png

J'ai essayé l'extraction linéaire par binarisation et conversion Hough, mais j'essaierai d'appliquer l'OCR par ROI (découpage d'une partie de l'image) uniquement sur la partie où les sous-titres sont susceptibles d'apparaître une fois.

Je me suis demandé si je ne pouvais extraire que les sous-titres gris de la zone, mais il m'est difficile de savoir ce que je suis susceptible de faire car je souffre de gens: criez:

développement de

import sys

import cv2
import os
import numpy as np

import pyocr
import pyocr.builders

from PIL import Image, ImageDraw, ImageFont

import time

def process(src):
	kernel = np.ones((3,3),np.uint8)
	gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)

	o_ret, o_dst = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)
	dst = cv2.morphologyEx(o_dst, cv2.MORPH_OPEN, kernel)
	return cv2.bitwise_not(dst)

def imageToText(tool, src):
	tmp_path = "temp.png "

	cv2.imwrite(tmp_path, src)
	dst = tool.image_to_string(
		Image.open(tmp_path),
		lang='jpn',
		builder=pyocr.builders.WordBoxBuilder(tesseract_layout=6)
	)

	sentence = []
	for item in dst:
		sentence.append(item.content)

	return "".join(sentence)


def createTextImage(src, sentence, px, py, color=(8,8,8), fsize=28):

	tmp_path = "src_temp.png "
	cv2.imwrite(tmp_path, src)

	img = Image.open(tmp_path)
	draw = ImageDraw.Draw(img)

	font = ImageFont.truetype("./IPAfont00303/ipag.ttf", fsize)
	draw.text((px, py), sentence, fill=color, font=font)
	img.save(tmp_path)
	return cv2.imread(tmp_path)



if __name__ == '__main__':

	tools = pyocr.get_available_tools()
	if len(tools) == 0:
		print("No OCR tool found")
		sys.exit(1)

	tool = tools[0]

	cap = cv2.VideoCapture('one_minutes.mp4')

	cap_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
	cap_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
	fps = cap.get(cv2.CAP_PROP_FPS)

	telop_height = 50

	fourcc = cv2.VideoWriter_fourcc('m','p','4','v')
	writer = cv2.VideoWriter('extract_telop_text.mp4',fourcc, fps, (cap_width, cap_height + telop_height))

	start = time.time()
	count = 0
	try :
		while True:
			if not cap.isOpened():
				break

			if cv2.waitKey(1) & 0xFF == ord('q'):
				break

			ret, frame = cap.read()

			if frame is None:
				break

			telop = np.zeros((telop_height, cap_width, 3), np.uint8)
			telop[:] = tuple((128,128,128))

			gray_frame = process(frame)
			roi = gray_frame[435:600, :]
			txt = imageToText(tool, roi)

			images = [frame, telop]

			frame = np.concatenate(images, axis=0)
			font = cv2.FONT_HERSHEY_SIMPLEX

			seconds = round(count/fps, 4)

			cv2.putText(frame, "{:.4f} [sec]".format(seconds), 
						(cap_width - 250, cap_height + telop_height - 10), 
						font, 
						1, 
						(0, 0, 255), 
						2, 
						cv2.LINE_AA)

			writer.write(createTextImage(frame, txt, 20, cap_height + 10))
			count += 1

			print("{}[sec]".format(seconds))

	except cv2.error as e:
		print(e)	

	writer.release()
	cap.release()

	print("Done!!! {}[sec]".format(round(time.time() - start,4)))

Supplément

―― J'utilise PIL au lieu d'openCV pour écrire des caractères japonais, mais lorsque je transmets les données, j'enregistre temporairement le fichier image. Pour cette raison, il a fallu plus de 10 minutes pour générer la vidéo: sweat_smile: Y a-t-il un bon moyen: déçu_relieved:

Exemple)


tmp_path = "src_temp.png "
#Sortie des données d'image utilisées dans openCV
cv2.imwrite(tmp_path, src)

#Lire les données avec PIL
img = Image.open(tmp_path)

--Le flux avant la reconnaissance de caractères est le suivant.

  1. Image en noir et blanc
  2. Traitement de binarisation par formule Otsu
  3. Élimination du bruit par processus d'ouverture (rétrécissement-> agrandissement)
  4. Inversez l'image
def process(src):
	kernel = np.ones((3,3),np.uint8)
	gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)

	o_ret, o_dst = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)
	dst = cv2.morphologyEx(o_dst, cv2.MORPH_OPEN, kernel)
	return cv2.bitwise_not(dst)

résultat

extract_telop_text.gif

Kampe interfère un peu avec la reconnaissance des caractères, mais je pense qu'il peut être lu dans une certaine mesure.

en conclusion

Ensuite, essayons la reconnaissance de caractères à l'aide de l'API Google Cloud Vision. J'ai essayé la démo de https://cloud.google.com/vision/, mais la précision est toujours élevée. demo.png

Lien utile

Recommended Posts

J'ai essayé d'extraire des caractères des sous-titres (OpenCV: édition tesseract-ocr)
J'ai essayé d'extraire des caractères des sous-titres (OpenCV: API Google Cloud Vision)
J'ai essayé d'extraire des fonctionnalités avec SIFT d'OpenCV
J'ai essayé d'extraire des noms de joueurs et de compétences d'articles sportifs
J'ai essayé de résumer les modules d'Ansible - l'édition Linux
J'ai essayé de détecter rapidement un mouvement avec OpenCV
J'ai essayé d'ajouter un post-incrément à l'édition CPython Extra
J'ai essayé d'extraire le dessin au trait de l'image avec Deep Learning
J'ai essayé d'exécuter du code Python à partir de .Net en utilisant Pythonnet (édition Hallo World)
J'ai essayé de déboguer.
J'ai essayé de détecter l'iris à partir de l'image de la caméra
J'ai essayé de devenir un Ann Man en utilisant OpenCV
[Deep Learning from scratch] J'ai essayé d'expliquer le décrochage
J'ai essayé d'extraire diverses informations du PC distant de Python par la bibliothèque WMI
J'ai essayé de créer une API list.csv avec Python à partir de swagger.yaml
J'ai essayé d'apprendre PredNet
J'ai essayé d'organiser SVM.
J'ai essayé d'implémenter PCANet
J'ai essayé de reconnaître le visage de la vidéo (OpenCV: version python)
J'ai essayé de réintroduire Linux
J'ai essayé de présenter Pylint
J'ai essayé de résumer SparseMatrix
J'ai essayé de changer le script python de 2.7.11 à 3.6.0 sur Windows10
J'ai essayé de traduire de force des sous-titres anglais en japonais avec Udemy
jupyter je l'ai touché
J'ai essayé d'implémenter Perceptron Part 1 [Deep Learning from scratch]
J'ai essayé d'implémenter StarGAN (1)
J'ai essayé d'obtenir diverses informations de l'API codeforces
J'ai essayé d'implémenter SSD avec PyTorch maintenant (édition du modèle)
J'ai essayé d'obtenir rapidement des données d'AS / 400 en utilisant pypyodbc
J'ai essayé de résoudre l'édition du débutant du livre des fourmis avec python
J'ai essayé de faire la reconnaissance de caractères manuscrits de Kana Partie 1/3 D'abord à partir de MNIST
J'ai essayé de traiter l'image en "style croquis" avec OpenCV
J'ai essayé de numériser le tampon estampé sur papier en utilisant OpenCV
J'ai essayé d'afficher le temps de lecture de la vidéo (OpenCV: version Python)
J'ai essayé de traiter l'image dans un "style de dessin au crayon" avec OpenCV
J'ai essayé de couper une image fixe de la vidéo
J'ai essayé d'obtenir rapidement des données d'AS / 400 en utilisant pypyodbc Préparation 1
[Python] Essayez de reconnaître les caractères des images avec OpenCV et pyocr
J'ai essayé de créer une fonction de similitude d'image avec Python + OpenCV
J'ai essayé d'implémenter Deep VQE
J'ai essayé de créer l'API Quip
J'ai essayé de toucher Python (installation)
J'ai essayé d'utiliser GrabCut d'OpenCV
J'ai essayé de mettre en place une validation contradictoire
J'ai essayé d'expliquer l'ensemble de données de Pytorch
J'ai essayé l'authentification vocale Watson (Speech to Text)
J'ai touché l'API de Tesla
J'ai essayé la mise en file d'attente des tâches de Celery
J'ai essayé de m'organiser à propos de MCMC.
J'ai essayé d'implémenter Realness GAN
J'ai essayé de déplacer le ballon
J'ai essayé la reconnaissance faciale avec OpenCV
J'ai essayé d'estimer la section.
[Bases de la science des données] J'ai essayé d'enregistrer de csv à mysql avec python
[Deep Learning from scratch] J'ai essayé d'implémenter la couche sigmoïde et la couche Relu
Mayungo's Python Learning Episode 2: J'ai essayé de mettre des caractères avec des variables