Sending Batch request to azure cognitive API for TEXT-OCR - azure

I am calling the Azure cognitive API for OCR text-recognization and I am passing 10-images at the same time simultaneously (as the code below only accepts one image at a time-- that is 10-independent requests in parallel) which is not efficient to me, regardin processing point of view, as I need to use extra modules i.e: Celery and multiprocessing.
So, is there a way to send all the 10-images in a single request and get the output at once then do post processing?
import time
from io import BytesIO
import cv2
import requests
from PIL import Image as PILImage
from PIL import Image
file_list = []
headers = {
"Ocp-Apim-Subscription-Key": "<API-KEY>",
'Content-Type': 'application/octet-stream'}
p = "symbol_sample.jpg"
print(p,"p")
def recognise_text(p):
p = cv2.imread(p)
cropped_image = PILImage.fromarray(p)
buffer = BytesIO()
cropped_image.save(buffer, format="JPEG")
image_bytes = buffer.getvalue()
try:
response = requests.post(
"https://centralindia.api.cognitive.microsoft.com/vision/v2.0/recognizeText?mode=Printed",
headers=headers,
data=image_bytes
)
header_link = str(response.headers['Operation-Location'])
while (True):
headers_get = {
"Ocp-Apim-Subscription-Key": "<API-KEY>"",
'Content-Type': 'application/json'
}
result = requests.get(
url=header_link,
headers=headers_get
)
response_r = result.json()
if response_r["status"] == "Succeeded":
return response_r
else:
time.sleep(4)
except Exception as e:
print(e)
return ""
image1="symbol_sample.jpg"
o = recognise_text(image1)
print(o)
Any help would be really appreciated.

I guess you are looking for Batch Read File
public class BatchReadFileSample
{
public static async Task RunAsync(string endpoint, string key)
{
ComputerVisionClient computerVision = new ComputerVisionClient(new ApiKeyServiceClientCredentials(key))
{
Endpoint = endpoint
};
const int numberOfCharsInOperationId = 36;
string localImagePath = #"Images\handwritten_text.jpg"; // See this repo's readme.md for info on how to get these images. Alternatively, you can just set the path to any appropriate image on your machine.
string remoteImageUrl = "https://github.com/Azure-Samples/cognitive-services-sample-data-files/raw/master/ComputerVision/Images/printed_text.jpg";
Console.WriteLine("Text being batch read ...");
await BatchReadFileFromStreamAsync(computerVision, localImagePath, numberOfCharsInOperationId);
await BatchReadFileFromUrlAsync(computerVision, remoteImageUrl, numberOfCharsInOperationId);
}
// Read text from a remote image
private static async Task BatchReadFileFromUrlAsync(ComputerVisionClient computerVision, string imageUrl, int numberOfCharsInOperationId)
{
if (!Uri.IsWellFormedUriString(imageUrl, UriKind.Absolute))
{
Console.WriteLine("\nInvalid remote image url:\n{0} \n", imageUrl);
return;
}
// Start the async process to read the text
BatchReadFileHeaders textHeaders = await computerVision.BatchReadFileAsync(imageUrl);
await GetTextAsync(computerVision, textHeaders.OperationLocation, numberOfCharsInOperationId);
}
// Recognize text from a local image
private static async Task BatchReadFileFromStreamAsync(ComputerVisionClient computerVision, string imagePath, int numberOfCharsInOperationId)
{
if (!File.Exists(imagePath))
{
Console.WriteLine("\nUnable to open or read local image path:\n{0} \n", imagePath);
return;
}
using (Stream imageStream = File.OpenRead(imagePath))
{
// Start the async process to recognize the text
BatchReadFileInStreamHeaders textHeaders = await computerVision.BatchReadFileInStreamAsync(imageStream);
await GetTextAsync(computerVision, textHeaders.OperationLocation, numberOfCharsInOperationId);
}
}
Here is the Full Code

Related

Problems about concurrent task in FastAPI

dear community
I've tried to execute async def in FastAPI app.
the workflow is crate FastAPI service to recieve from end-user requests and send it to another service such as DB Writer service.
first, I've create async def for send request with aiosonic library
Here's the code
import aiosonic
from aiosonic.timeout import Timeouts
async def db_writer_requests(arrival_input, prediction_out) :
client = aiosonic.HTTPClient()
timeouts_settings = Timeouts(sock_connect = 10,sock_read = 10)
await client.post('http://127.0.0.1:8082/api/motor/writer/test1',
headers = {'Content-Type' : 'application/json'},
json = arrival_input,
timeouts = timeouts_settings)
client.shutdown()
Here's main app
#app.post('/api/motor/test')
async def manager_api(raw_input:arrival_requests) :
depart_json = dict(raw_input)
inc_preds, model_error = await predict_requests(depart_json)
if (inc_preds == None) or (inc_preds['status_code'] != 200) :
return inc_preds if model_error == None else model_error
else :
mlid = uuid.uuid4()
pred_output = model_output(
predict_uuid = str(mlid),
net_premium = str(inc_preds["result"]["data"]["net_premium"]),
car_repair = str(inc_preds["result"]["data"]["car_repair"]),
place_repair = str(inc_preds["result"]["data"]["place_repair"]),
insurer_tier = str(inc_preds["result"]["data"]["insurer_tier"])
)
send_msg = good_response_msg(
status = 'OK',
status_code = 200,
result = data(
data = pred_output
)
)
await db_writer_requests(depart_json,dict(pred_output))
return send_msg
when I've tried to send request.
case 1 I've not to use "await", the program not send request to service and not show any response in endpoint service.
case 2 I've use await it worked normally, but if endpoint service not available the main service shown "Internal Server Error".
Thank you for Advance

Sending openCV image via Flask_socketIO to client causes TypeError: Object of type ndarray is not JSON serializable

I have a base64 image being sent from the browser to my flask server. When the server gets the base64 string, it converts it to a format for OpenCV:
image = '{}'.format(image64).split(',')[1]
im_bytes = base64.b64decode(image)
im_arr = np.frombuffer(im_bytes, dtype=np.uint8) # im_arr is one-dim Numpy array
frame = cv2.imdecode(im_arr, flags=cv2.IMREAD_COLOR)
Some processing happens on the frame and then, using flask_signalio, is sent back to the browser using:
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 90]
result, encimg = cv2.imencode('.jpg', updated_frame, encode_param)
socketio.emit('response_back', {'image_data': encimg}, namespace='/test')
In the browser, I have some JS to display the image that it receives:
socket.on('response_back', function(image){
....
});
I have two issues.
Calling socketio.emit('response_back', {'image_data': encimg}, namespace='/test') results in an exception on the server: TypeError: Object of type ndarray is not JSON serializable.
How can I fix this? What is wrong here? It's strange because I am sure I am sending ('emitting') the data correctly, as shown here and here. I've also tried setting up SocketIO to use binary data: socketio = SocketIO(app, binary=True). Nothing works. Always the same error.
How do I deal with the image data back on the client/browser? (i.e. in the socket.on('response_back', function(image) code)?
After nearly an hour, I've found the solution.
First, flask_socketio can send byte data, but NOT ndarray! The solution is to encode to bytes, with .tobytes(). For example, on the server:
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 90]
result, encimg = cv2.imencode('.jpg', updated_frame, encode_param)
socketio.emit('response_back', {'frame': encimg.tobytes()}, namespace='/test')
For the second problem, we need to convert the ArrayBuffer data:
var arrayBufferView = new Uint8Array( result.frame );
var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } );
var urlCreator = window.URL || window.webkitURL;
var imageUrl = urlCreator.createObjectURL( blob );
var image_id = document.getElementById('imagebox');
image_id.src = imageUrl;

move a downloaded file from python backend(Rest API) to /storage/emulated/0/Download in flutter

Basically I'll provide a input field in the mobile app where user's will paste the YouTube Url & sends the url to the backend Rest API,the Rest API will download the video.The problem is video should get downloaded to this location /storage/emulated/0/Download of the mobile storage
Error, the videos is getting downloaded in the backend.I.e on my local machine instead of mobile storage location
Rest API code for downloading the video
from flask import Flask, request, jsonify
from pytube import YouTube
import os
app = Flask(__name__)
#app.route('/Youtube', methods=["POST"])
def youtube():
youtube_link_request = request.get_json(force=False, silent=False, cache=True)
print(youtube_link_request)
youtube_link = youtube_link_request['link']
downloads = youtube_link_request['path']
print(downloads);
yt = YouTube(youtube_link).streams.first().download()
## YouTube(youtube_link).streams.first().download() will starting downloading the video
views = YouTube(youtube_link).views
thumbnail = YouTube(youtube_link).thumbnail_url
title = YouTube(youtube_link).title
# streams_data = yt.streams.first().download()
# streams = []
# for stream in streams_data:
# stream_info = stream
# streams.append(stream_info.type)
return jsonify({"Data": "successful completed",
"views": views,
"thumbnail": thumbnail,
"title": title,
}), 200
if __name__ == "__main__":
app.run(debug=True)
Apart of flutter code
RaisedButton(
onPressed: () async {
final PermissionHandler _permissionHandler =
PermissionHandler();
var result = await _permissionHandler
.requestPermissions([PermissionGroup.storage]);
// var dir = await
if (_formkey.currentState.validate()) {
if (result[PermissionGroup.storage] ==
PermissionStatus.granted) {
var dirpath =
await ExtStorage.getExternalStoragePublicDirectory(
ExtStorage.DIRECTORY_DOWNLOADS);
final UrlModel = await passInfo(urlTextController.text);
// _loading ? LinearProgressIndicator() : _urlModel;
setState(() {
_loading = !_loading;
_urlModel = UrlModel;
views = _urlModel.views;
title = _urlModel.title;
thumbnail = _urlModel.thumbnail;
});
print(dirpath);
}
// print(title);
Fluttertoast.showToast(
msg: "${_urlModel.title}",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1);
} else {
Fluttertoast.showToast(
msg: "Error",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1);
}
},
child: Text('Submit'),
),
It looks logical to me, You need to run a webserver like Nginx and copy all downloaded files to your webserver root directory, then you have your server host address with the address of the file, so it will be like this server_ip:server_port/name_of_the_file_downloaded.mkv, provide it to the flutter app, so the user will download it to /storage/emulated/0/Download.

Is there a way to use Spark to load a file in FTP using TLS

I am in the process of moving a python process to Spark. In python we are using ftplib to connect and download a file to a EC2 instance. Once file is downloaded, we are uploading to S3. We are transitioning to severless infrastructure and would like to load file in spark via AWS Glue and then use mulit-part upload to move it to S3. I have tried to just run the current code in a in a larger glue instance type but the machine still runs out of memory (20gb file).
old python code
"""
This script will get the backup file
"""
import sys
from datetime import datetime
import re
import ftplib
from retry import retry
import shutil
from tools.python.s3_functions import s3_upload
from python_scripts.get import *
def get_ftp_connector(path, user, password):
ftp = ftplib.FTP_TLS(path)
ftp.login(user, password)
ftp.prot_p()
return ftp
def get_ftp_files_list(ftp, dir):
ftp.cwd(dir)
files = ftp.nlst()
print(str("-".join(files)))
if "filecompleted.txt" not in files:
print("Failed to find filescompleted.txt file in ftp server.")
raise Exception("Failed to find filescompleted.txt file in ftp server.")
regex_str = 'Backup_File_Mask_Goes_here([\d]{8}).bak'
find_date_regex = re.compile(regex_str)
searched = [(f, find_date_regex.match(f)) for f in files if find_date_regex.match(f)]
searched = \
[(file_name, datetime.strptime(regex_result.groups()[0], '%Y%m%d')) for file_name, regex_result in searched]
searched = sorted(searched, key=lambda elem: elem[1], reverse=True)
if not searched:
print("Failed to find appropriate file in ftp server.")
raise Exception("Failed to find appropriate file in ftp server.")
return searched[0]
class FtpUploadTracker:
size_written = 0
total_size = 0
last_shown_percent = "X"
def __init__(self, total_size, bk_file):
self.total_size = total_size
self.bk_file = bk_file
self.output_file = open(self.bk_file, 'wb')
self.start_time = datetime.now()
def handle(self, block):
self.size_written += len(block)
percent_complete = str(round((self.size_written / self.total_size) * 100, 1))
self.output_file.write(block)
time_elapsed = (datetime.now() - self.start_time).total_seconds()
speed = round(self.size_written / (1000 * 1000 * time_elapsed), 2)
msg = "{percent}% complete # average speed of {speed}MB/s : total run time {minutes}m".\
format(percent=percent_complete, speed=speed, minutes=round(time_elapsed/60))
if time_elapsed > 600 and speed < 1:
print("Zombie connection, failing dl.")
raise Exception("Zombie connection, failing dl.")
if self.last_shown_percent != percent_complete:
self.last_shown_percent = percent_complete
print(msg)
def close(self):
self.output_file.close()
#retry(tries=4, delay=300)
def retrieve_db():
"""
This function will retrieve via FTP the backup
:return: None
"""
ftp = get_ftp_connector(FTP_PATH, FTP_USER, FTP_PASSWORD)
# return back the most recent entry
file_name, file_date = get_ftp_files_list(ftp, 'database')
file_epoch = (file_date - datetime(1970, 1, 1)).total_seconds()
new_file_name = "backup_{epoch}.bak".format(epoch=str(int(file_epoch)))
if os.path.exists(DATAFILEPATH):
shutil.rmtree(DATAFILEPATH)
if not os.path.exists(DATAFILEPATH):
os.makedirs(DATAFILEPATH)
temp_backup_file_location = os.path.join(DATAFILEPATH + new_file_name)
print("Found file {file_name}, and downloading it to {loc}".
format(file_name=file_name, loc=temp_backup_file_location))
ftp_handler = FtpUploadTracker(ftp.size(file_name), temp_backup_file_location)
ftp.retrbinary("RETR " + file_name, ftp_handler.handle)
ftp.quit()
ftp_handler.close()
print("Finished download. Uploading to S3.")
s3_upload(DATAFILEPATH, new_file_name, bucket, "db_backup")
os.remove(temp_backup_file_location)
def main():
try:
retrieve_db()
except Exception as e:
print("Failed to download backup after 4 tries with error {e}.".format(e=e))
return 1
return 0
if __name__ == "__main__":
rtn = main()
sys.exit(rtn)
New Spark Code (in progress): The username has a | character that made me encode the uri. When I run the code, I get a connection refused. I am able to use same connection info for python.
from pyspark import SparkContext
from pyspark import SparkFiles
import urllib
sc = SparkContext()
ftp_path = "ftp://Username:password#ftplocation.com/path_to_file"
file_path_clean = urllib.parse.urlencode(ftp_path, safe='|')
print(f"file_path_clean: {file_path_clean}")
sc.addFile(ftp_path)
filename = SparkFiles.get(file_path.split('/')[-1])
print(f"filename: {filename}")
rdd = sc.textFile("file://" + filename)
print("We got past rdd = sc.textFile(file:// + filename)")
rdd.take(10)
rdd.collect()
print(rdd)
There are three ways to approach the problem:
Use a mounted file system backed by FTP and write to it from Spark.
Use a Spark to SFTP connector such as spark-sftp.
Write the files with Spark somewhere else and copy to SFTP as a separate step. Due to the various reliability issues with SFTP and the fact that Spark leaves partial output during failed write operations, which is the path that we've taken. We write terabytes to SFTP endpoints using code that looks like the following in Scala. I hope it can be helpful for you Python work.
/** Defines some high-level operations for interacting with remote file protocols like FTP, SFTP, etc.
*/
trait RemoteFileOperations extends Closeable {
var backoff: BlockingRetry.Backoff = Backoff.linear(3000)
var retry: BlockingRetry.Retry = Retry.maxRetries(3)
var recover: Recovery = recoverable(this)
var ignore: Ignored = nonRecoverable
def listFiles(path: String = ""): Seq[FInfo]
def uploadFile(localPath: String, remoteDirectory: String): Unit
def downloadFile(localPath: String, remotePath: String): Unit
def deleteAll(path: String): Unit
def connect(): Unit = {}
def disconnect(): Unit = {}
def reconnect(): Unit = {
disconnect()
connect()
}
override def close(): Unit = disconnect()
/** Wraps a block of code and allows it to be retried when [[recoverable()]] conditions
* are met. [[BlockingRetry.retry()]] is called with the var fields
* [[backoff]], [[retry]], [[recover]], and [[ignore]], which can all be reconfigured.
*/
def retryable[A](f: => A): A = {
BlockingRetry.retry(retry, backoff, recover, ignore) {
f
}
}
def recoverable(fileOp: RemoteFileOperations): Recovery = {
case (_: SocketTimeoutException, _: Int) =>
fileOp.reconnect()
None
}
def nonRecoverable: Ignored = {
case _: UnknownHostException |
_: SSLException |
_: SocketException |
_: IllegalStateException =>
}
}
class SSHJClient(host: String, username: String, password: String) extends RemoteFileOperations {
import net.schmizz.keepalive.KeepAliveProvider
import net.schmizz.sshj.connection.ConnectionException
import net.schmizz.sshj.sftp.SFTPClient
import net.schmizz.sshj.transport.verification.PromiscuousVerifier
import net.schmizz.sshj.xfer.FileSystemFile
import net.schmizz.sshj.{DefaultConfig, SSHClient}
override def listFiles(path: String): Seq[FInfo] = {
import collection.JavaConverters._
retryable {
sftpSession(sftp => {
sftp.ls(path).asScala
.filter(f => f.getName != "." && f.getName != "..")
.map(f => FInfo(f.getPath, f.getParent, f.isDirectory, f.getAttributes.getSize, f.getAttributes.getMtime))
})
}
}
override def uploadFile(localPath: String, remoteDirectory: String): Unit = {
retryable {
sftpSession(sftp => {
sftp.getFileTransfer.setPreserveAttributes(false)
sftp.put(new FileSystemFile(localPath), remoteDirectory)
})
}
}
override def downloadFile(localPath: String, remotePath: String): Unit = {
retryable {
sftpSession(sftp => {
sftp.getFileTransfer.setPreserveAttributes(false)
sftp.get(remotePath, new FileSystemFile(localPath))
})
}
}
override def deleteAll(path: String): Unit =
throw new UnsupportedOperationException("#deleteAll is unsupported for SSHJClient")
private def sftpSession[A](f: SFTPClient => A): A = {
val defaultConfig = new DefaultConfig()
defaultConfig.setKeepAliveProvider(KeepAliveProvider.KEEP_ALIVE)
val ssh = new SSHClient(defaultConfig)
try {
// This is equivalent to StrictHostKeyChecking=no which is disabled since we don't usually know
// the SSH remote host key ahead of time.
ssh.addHostKeyVerifier(new PromiscuousVerifier())
ssh.connect(host)
ssh.authPassword(username, password)
val sftp = ssh.newSFTPClient()
try {
f(sftp)
} finally {
sftp.close()
}
} finally {
ssh.disconnect()
}
}
override def recoverable(fileOp: RemoteFileOperations): Recovery = {
super.recoverable(fileOp).orElse {
case (e: ConnectionException, _: Int) =>
println(s"Recovering session from exception: $e")
None
}
}
}

How can we use microphone in google colab?

OSError Traceback (most recent call last)
<ipython-input-21-4159a88154c9> in <module>()
7 response = google_images_download.googleimagesdownload()
8 r = sr.Recognizer()
----> 9 with sr.Microphone() as source:
10 print("Say something!")
11 audio = r.listen(source)
/usr/local/lib/python3.6/dist-packages/speech_recognition/init.py in init(self, device_index, sample_rate, chunk_size)
84 assert 0 <= device_index < count, "Device index out of range ({} devices available; device index should be between 0 and {} inclusive)".format(count, count - 1)
85 if sample_rate is None: # automatically set the sample rate to the hardware's default sample rate if not specified
---> 86 device_info = audio.get_device_inf o_by_index(device_index) if device_index is not None else audio.get_default_input_device_info()
87 assert isinstance(device_info.get("defaultSampleRate"), (float, int)) and device_info["defaultSampleRate"] > 0, "Invalid device info returned from PyAudio: {}".format(device_info)
88 sample_rate = int(device_info["defaultSampleRate"])
Here's an example that shows how to access a user's camera and microphone:
https://colab.research.google.com/notebooks/snippets/advanced_outputs.ipynb#scrollTo=2viqYx97hPMi
The snippet you linked above attempts to access a microphone in Python. That won't work because there's no microphone attached to the virtual machine which executes Python code in Colab.
Instead, you want to access the microphone of the computer running the web browser. Then, capture data there, and pass it back to the virtual machine for processing in Python.
That's what's shown in the snippet linked above.
Here is a simple snippet
from IPython.display import HTML, Audio
from google.colab.output import eval_js
from base64 import b64decode
import numpy as np
from scipy.io.wavfile import read as wav_read
import io
import ffmpeg
AUDIO_HTML = """
<script>
var my_div = document.createElement("DIV");
var my_p = document.createElement("P");
var my_btn = document.createElement("BUTTON");
var t = document.createTextNode("Press to start recording");
my_btn.appendChild(t);
//my_p.appendChild(my_btn);
my_div.appendChild(my_btn);
document.body.appendChild(my_div);
var base64data = 0;
var reader;
var recorder, gumStream;
var recordButton = my_btn;
var handleSuccess = function(stream) {
gumStream = stream;
var options = {
//bitsPerSecond: 8000, //chrome seems to ignore, always 48k
mimeType : 'audio/webm;codecs=opus'
//mimeType : 'audio/webm;codecs=pcm'
};
//recorder = new MediaRecorder(stream, options);
recorder = new MediaRecorder(stream);
recorder.ondataavailable = function(e) {
var url = URL.createObjectURL(e.data);
var preview = document.createElement('audio');
preview.controls = true;
preview.src = url;
document.body.appendChild(preview);
reader = new FileReader();
reader.readAsDataURL(e.data);
reader.onloadend = function() {
base64data = reader.result;
//console.log("Inside FileReader:" + base64data);
}
};
recorder.start();
};
recordButton.innerText = "Recording... press to stop";
navigator.mediaDevices.getUserMedia({audio: true}).then(handleSuccess);
function toggleRecording() {
if (recorder && recorder.state == "recording") {
recorder.stop();
gumStream.getAudioTracks()[0].stop();
recordButton.innerText = "Saving the recording... pls wait!"
}
}
// https://stackoverflow.com/a/951057
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
var data = new Promise(resolve=>{
//recordButton.addEventListener("click", toggleRecording);
recordButton.onclick = ()=>{
toggleRecording()
sleep(2000).then(() => {
// wait 2000ms for the data to be available...
// ideally this should use something like await...
//console.log("Inside data:" + base64data)
resolve(base64data.toString())
});
}
});
</script>
"""
def get_audio():
display(HTML(AUDIO_HTML))
data = eval_js("data")
binary = b64decode(data.split(',')[1])
process = (ffmpeg
.input('pipe:0')
.output('pipe:1', format='wav')
.run_async(pipe_stdin=True, pipe_stdout=True, pipe_stderr=True, quiet=True, overwrite_output=True)
)
output, err = process.communicate(input=binary)
riff_chunk_size = len(output) - 8
# Break up the chunk size into four bytes, held in b.
q = riff_chunk_size
b = []
for i in range(4):
q, r = divmod(q, 256)
b.append(r)
# Replace bytes 4:8 in proc.stdout with the actual size of the RIFF chunk.
riff = output[:4] + bytes(b) + output[8:]
sr, audio = wav_read(io.BytesIO(riff))
return audio, sr
then run this
audio, sr = get_audio()
you might need to install this one
!pip install ffmpeg-python

Resources