[PYTHON] Ich habe versucht, Zeichen aus Untertiteln zu extrahieren (OpenCV: Google Cloud Vision API)

Motive Ich habe versucht, Zeichen aus Untertiteln zu extrahieren (OpenCV: tesseract-ocr edition) Google CloudVision API Ich möchte vision /) verwenden, um die Zeichen in den Untertiteln zu extrahieren.

Method Um die Google Cloud Vision-API verwenden zu können, müssen Sie zunächst ein Konto in der Google Cloud-Konsole registrieren und einen API-Schlüssel erhalten. Informationen zur Methode finden Sie unter Zusammenfassung der Verwendung der Cloud Vision-API (mit Beispielcode).

import requests
import json
import base64
import cv2
import sys

if __name__ == "__main__":
	KEY = "--- your api key ---"
	url = 'https://vision.googleapis.com/v1/images:annotate?key='
	api_url = url + KEY
	#Bild wird geladen
	img_file_path = sys.argv[1]
	mat = cv2.imread(img_file_path)
	#Nur Untertitel-Anzeigeteil
	roi = mat[435:600, :]

	# openCV -> base64
	result, dst_data = cv2.imencode('.png', roi)
	img_content = base64.b64encode(dst_data)

	#Anforderungshauptteil erstellen
	req_body = json.dumps({
	    'requests': [{
	        'image': {
	            'content': img_content.decode('utf-8')
	        },
	        'features': [{
				'type': 'DOCUMENT_TEXT_DETECTION'
	        }]
	    }]
	})

	#Ausstellung anfordern
	res = requests.post(api_url, data=req_body)
	#Holen Sie sich Bildinformationen von der Anfrage
	res_json = res.json()['responses']
	if 0 < len(res_json[0]):
		textobj = res_json[0]['textAnnotations'][0]
		print("".join(textobj["description"].strip().split("\n")))

Wenn ich eine API anfordere, entwerfe ich json, indem ich das Bild in base64 konvertiere.


src = cv2.imread("image_path")
result, dst_data = cv2.imencode('.png', src)
img_content = base64.b64encode(dst_data)

Sie können von openCV mit konvertieren.

Darüber hinaus ist es ausreichend, Zeichen zu extrahieren, während die API so wie sie ist sequentiell verarbeitet wird. Die Verarbeitungsgeschwindigkeit erhöht sich jedoch, wenn die parallele Verarbeitung mit "asyncio" durchgeführt wird. Der Grund für die Verwendung von "asyncio" ist, dass es stabiler als "multiprocessing.Pool" ist, da es die API-Antwortverarbeitung innerhalb des Collouts blockiert.


async def main_image_process(src):
	#Wird verarbeitet, um die Zeichenerkennung zu vereinfachen
	gray_frame = pre_process(src.content)
	#Schneiden Sie nur dort, wo Telop wahrscheinlich erscheint
	roi = gray_frame[435:600, :]
	#Text extrahieren
	text = await extractTelopText(roi)
	await asyncio.sleep(2)
	dst = await createFooterTelop(src.content)
	dst = await addJapaneseTelop(dst, text, 20, cap_height + telop_height - 30)
	dst = await addASCIITelop(dst, str(src.timestamp) + "[sec]", cap_width - 250, cap_height + telop_height - 10, color=(0,255,0))
	return MovieFrame(src.id, dst, src.timestamp)

if __name__ == "__main__":
	r = []
	loop = asyncio.get_event_loop()
	try:
		r = loop.run_until_complete(
			asyncio.gather(*[main_image_process(f) for f in frames])
		)
	finally:
		loop.close()

Es scheint, dass es einfacher mit Python 3.7 oder höher geschrieben werden kann, aber es ist noch nicht stabil und das Standardpaket von centOS war Python 3.6, also schreibe ich es basierend auf 3.6.

Development

Der ganze Code.

import sys
import cv2
import io
import os
import numpy as np
import base64
import json
import requests
import asyncio
from PIL import Image, ImageDraw, ImageFont
from collections import namedtuple
import time

MovieFrame = namedtuple("MovieFrame", ["id", "content", "timestamp"])
telop_height = 50
cap_width = 1
cap_height = 1

def pre_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)
	dst = cv2.bitwise_not(dst)
	dst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR)
	return dst

async def extractTelopText(src):
	KEY = "--- your api key ---"
	url = 'https://vision.googleapis.com/v1/images:annotate?key='
	api_url = url + KEY

	message = ""
	result, dst_data = cv2.imencode('.png', src)
	img_content = base64.b64encode(dst_data)
	#Anforderungshauptteil erstellen
	req_body = json.dumps({
	    'requests': [{
	        'image': {
	            'content': img_content.decode('utf-8')
	        },
	        'features': [{
				'type': 'DOCUMENT_TEXT_DETECTION'
	        }]
	    }]
	})
	#Ausstellung anfordern
	res = requests.post(api_url, data=req_body)
	#Holen Sie sich Bildinformationen von der Anfrage
	res_json = res.json()['responses']
	if 0 < len(res_json[0]):
		textobj = res_json[0]["textAnnotations"][0]
		message = "".join(textobj["description"].strip().split("\n"))
	return message

async def createFooterTelop(src):
	telop = np.zeros((telop_height, cap_width, 3), np.uint8)
	telop[:] = tuple((128,128,128))
	images = [src, telop]
	dst = np.concatenate(images, axis=0)
	return dst

async def main_image_process(src):
	#Wird verarbeitet, um die Zeichenerkennung zu vereinfachen
	gray_frame = pre_process(src.content)
	#Schneiden Sie nur dort, wo Telop wahrscheinlich erscheint
	roi = gray_frame[435:600, :]
	#Text extrahieren
	text = await extractTelopText(roi)
	await asyncio.sleep(2)

	dst = await createFooterTelop(src.content)
	dst = await addJapaneseTelop(dst, text, 20, cap_height + telop_height - 30)
	dst = await addASCIITelop(dst, str(src.timestamp) + "[sec]", cap_width - 250, cap_height + telop_height - 10, color=(0,255,0))
	return MovieFrame(src.id, dst, src.timestamp)


async def addASCIITelop(src, sentence, px, py, color=(8,8,8), fsize=28):
	cv2.putText(src, sentence, 
						(px, py), 
						cv2.FONT_HERSHEY_SIMPLEX, 
						1, 
						color, 
						2, 
						cv2.LINE_AA)	
	return src


async def addJapaneseTelop(src, sentence, px, py, color=(8,8,8), fsize=28):
	rgbImg = cv2.cvtColor(src, cv2.COLOR_BGR2RGB)
	canvas = Image.fromarray(rgbImg).copy()
	draw = ImageDraw.Draw(canvas)
	font = ImageFont.truetype("./IPAfont00303/ipag.ttf", fsize)
	draw.text((px, py), sentence, fill=color, font=font)
	
	dst = cv2.cvtColor(np.array(canvas, dtype=np.uint8), cv2.COLOR_RGB2BGR)
	return dst

if __name__ == '__main__':

	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_async.mp4',fourcc, fps, (cap_width, cap_height + telop_height))

	frames = []

	start = time.time()
	idx = 0
	#read frame
	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

			frames.append(MovieFrame(idx,frame, round(idx/fps, 4)) )
			idx += 1
	except cv2.error as e:
		print(e)

	cap.release()
	print("read movie file")
	
	#process
	r = []
	loop = asyncio.get_event_loop()
	try:
		r = loop.run_until_complete(
			asyncio.gather(*[main_image_process(f) for f in frames])
		)
	finally:
		loop.close()

	#sort
	sorted_out = sorted(r, key=lambda x: x.id)

	#write frame
	try :
		for item in sorted_out:
			writer.write(item.content)
	except cv2.error as e:
		print(e)
	writer.release()
	
	print("write movie file")
	print("Done!!! {}[sec]".format(round(time.time() - start,4)))

Result

tesseract-ocr Verarbeitungszeit: 450 Sekunden ≒ 7,5 Minuten

GoogleCloudVisionAPI

Verarbeitungszeit: 1315 Sekunden ≒ 21 Minuten

Die asynchrone Verarbeitung bei Verwendung einer externen API hat eine Weile gedauert. Sie können jedoch feststellen, dass die Google CloudVision-API für die OCR-Genauigkeit besser geeignet ist.

Future Das nächste Mal denke ich darüber nach, das Video von Ich habe das Objekt mithilfe der Bildreparatur (inpaint) (OpenCV: C ++) zu bearbeiten. Ich denke darüber nach, es C ++ basierend auf dem von mir verwendeten Code zu machen. Wenn es darum geht

Reference

Recommended Posts

Ich habe versucht, Zeichen aus Untertiteln zu extrahieren (OpenCV: Google Cloud Vision API)
Ich habe versucht, Zeichen aus Untertiteln zu extrahieren (OpenCV: tesseract-ocr edition)
Ich habe versucht, die Google Cloud Vision-API zu verwenden
Ich habe die Google Cloud Vision-API zum ersten Mal ausprobiert
Ich habe versucht, mit der Cloud Vision API von GCP automatisch erotische Bilder von Twitter zu sammeln
Verwenden Sie die Google Cloud Vision-API von Python
Ich habe "License OCR" mit der Google Vision API ausprobiert
Bei der Einführung der Google Cloud Vision-API in Schienen habe ich die Dokumentation befolgt.
Ich habe "Receipt OCR" mit der Google Vision API ausprobiert
Ich habe versucht, Funktionen mit SIFT von OpenCV zu extrahieren
Ich habe versucht, API list.csv mit Python aus swagger.yaml zu erstellen
Versuchen Sie, Lebensmittelfotos mithilfe der Google Cloud Vision-API zu beurteilen
Ich habe versucht, verschiedene Informationen von der Codeforces-API abzurufen
Ich habe Teslas API berührt
Ich habe versucht, Spieler- und Fertigkeitsnamen aus Sportartikeln zu extrahieren
Google Cloud Vision API-Beispiel für Python
Ich habe versucht, die UnityCloudBuild-API von Python zu verwenden
Ich habe versucht, die COTOHA-API zu berühren
Ich habe eine Web-API erstellt
Verwendung der Cloud Vision API von GCP
Python ruft die Google Cloud Vision API von LINE BOT über AWS Lambda auf
Erkennen Sie japanische Zeichen anhand von Bildern mithilfe der Cloud Vision-API von Google mit Python
Ich habe versucht, die Qiita-API von Anfang an zu aktivieren
Ich habe versucht, mit OpenCV Bewegungen schnell zu erkennen
So rufen Sie die Cloud-API über GCP-Cloud-Funktionen auf
Verwendung der Google Cloud Translation API
[IBM Cloud] Ich habe versucht, über Cloud Funtions (Python) auf die Tabelle Db2 on Cloud zuzugreifen.
Ich habe versucht, die Strichzeichnung mit Deep Learning aus dem Bild zu extrahieren
Ich habe versucht, verschiedene Informationen von Remote-PC aus Python von WMI Library zu extrahieren
Ich habe versucht, von Postman aus mit Cisco Guest Shell als API-Server zu arbeiten
Ich habe versucht, Iris aus dem Kamerabild zu erkennen
Extrahieren Sie Zeichen aus Bildern mithilfe der Zeichenerkennungs-API von docomo
Ich habe versucht, eine ML-Pipeline mit Cloud Composer zu erstellen
Ich habe versucht, mit OpenCV Ann Man zu werden
Ich habe versucht, unsere Dunkelheit mit der Chatwork-API aufzudecken
Ich habe versucht, Dropout zu erklären
Ich habe versucht, mit Python auf Google Spread Sheets zuzugreifen
Ich habe versucht zu debuggen.
[Erste COTOHA-API] Ich habe versucht, die alte Geschichte zusammenzufassen
Ich habe versucht, mich mit Spring Boot + Spring Security REST API anzumelden
Ich habe ein Tool erstellt, um eine Wortwolke aus Wikipedia zu erstellen
Ich habe versucht, das Gesicht aus dem Video zu erkennen (OpenCV: Python-Version)
So verbergen Sie den Google Maps-API-Schlüssel vor HTML
Ich habe versucht, das Python-Skript unter Windows 10 von 2.7.11 auf 3.6.0 zu ändern
Ich habe versucht, englische Untertitel mit Udemy gewaltsam ins Japanische zu übersetzen
Ich habe versucht, Perceptron Teil 1 [Deep Learning von Grund auf neu] zu implementieren.
Ich habe versucht, mit pypyodbc schnell Daten von AS / 400 abzurufen
Ich habe versucht, PredNet zu lernen
Ich habe versucht, SVM zu organisieren.
Ich habe versucht, PCANet zu implementieren
Ich habe versucht, Linux wieder einzuführen
Ich habe versucht, Pylint vorzustellen
Ich habe versucht, SparseMatrix zusammenzufassen
jupyter ich habe es berührt
Ich habe versucht, StarGAN (1) zu implementieren.
Bis Sie die Google Cloud Vision-API ausprobieren (Erkennung schädlicher Bilder)
Ich habe versucht, Kanas handschriftliche Zeichenerkennung Teil 1/3 zuerst von MNIST zu machen