How to send an image from a telegram bot - python

I have my bot working by now, but the thing is it can only send text. I have seen in the Bot API there are functions to send photos, videos... but I can't get it to work. Someone has achieved it? I'm using python source code from yukuku/telebot
elif text == '/image':
img = Image.new('RGB', (512, 512))
base = random.randint(0, 16777216)
pixels = [base+i*j for i in range(512) for j in range(512)] # generate sample image
img.putdata(pixels)
output = StringIO.StringIO()
img.save(output, 'JPEG')
reply(img=output.getvalue())
When I change the code, nothing happened.
img = Image.open('image.png')
img.show()
Please help me. I need the correct code. Sorry for my bad English.

I have included two functions, one is good for sending local images, the other one is good for sending remote images.
def sendImage():
url = "https://api.telegram.org/bot<Token>/sendPhoto";
files = {'photo': open('/path/to/img.jpg', 'rb')}
data = {'chat_id' : "YOUR_CHAT_ID"}
r= requests.post(url, files=files, data=data)
print(r.status_code, r.reason, r.content)
def sendImageRemoteFile(img_url):
url = "https://api.telegram.org/bot<Token>/sendPhoto";
remote_image = requests.get(img_url)
photo = io.BytesIO(remote_image.content)
photo.name = 'img.png'
files = {'photo': photo}
data = {'chat_id' : "YOUR_CHAT_ID"}
r= requests.post(url, files=files, data=data)
print(r.status_code, r.reason, r.content)

The solution is
elif 'Hi' in text:
reply(img=urllib2.urlopen('img url').read())
or
if text == 'help':
reply(img=urllib2.urlopen('img url').read())

Before sending the photo, you have to do output.seek(0) to put the cursor back to the beginning of the file, else it will be read as zero

I understand the question. Here's the answer:
def sendImageFromUrl(url):
#this tweak added if request image failed
headers = {'user-agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7'}
response = requests.get(url, headers=headers)
#response = requests.get(url)
output = StringIO(response.content)
img = Image.open(output)
img.save(output, 'JPEG')
resp = multipart.post_multipart(BASE_URL + 'sendPhoto', [
('chat_id', str(chat_id)),
('caption', 'Your Caption'),
], [
('photo', 'image.jpg', output.getvalue()),
])
Make sure your server does have python module: requests.
You can download here: https://pypi.python.org/pypi/requests#downloads
And put in your application like this
/myapp/app.yaml
/myapp/main.py
/myapp/requests/packages/
/myapp/requests/__init__.py
/myapp/requests/adapters.py
etc...
Credit: https://stackoverflow.com/a/17128168/1097372
Put in main.py after line 10
import requests
from StringIO import StringIO

Related

Have an image link from iMDB api, how can I change it's size pyton

I am trying to work with IMDb API. My code thus far is
import http.client
import json
import requests
conn = http.client.HTTPSConnection("imdb-api.com", 443)
payload = ''
headers = {'User-agent': 'Chrome/95.0'}
conn.request("GET", "https://imdb-api.com/en/API/MostPopularMovies/<API_Key>",headers=headers)
res = conn.getresponse()
data = res.read()
convertedDict = json.loads(data.decode("utf-8"))
imagepath = r'venv/files/image.jpeg'
req = requests.get(convertedDict['items'][0]['image'], headers=headers)
with open(imagepath, 'wb') as file:
file.write(req.content)
This allows me to download the image of the first popular movie, however, the image size is really small. This is the link that I am downloading. I know that if I get rid of everything after # the image will become a lot larger. Is there a way to edit the link such that I can drop everything after # and even edit the numbers after UX with code?
Everything I try to do with string or URL operations give's me an error
https://m.media-amazon.com/images/M/MV5BZWMyYzFjYTYtNTRjYi00OGExLWE2YzgtOGRmYjAxZTU3NzBiXkEyXkFqcGdeQXVyMzQ0MzA0NTM#._V1_UX128_CR0,3,128,176_AL_.jpg
Thank you in advance
Explanation
(code example below)
Here's how to get a bigger image of the size you want. Given this URL,
https://m.media-amazon.com/images/M/MV5BZWMyYzFjYTYtNTRjYi00OGExLWE2YzgtOGRmYjAxZTU3NzBiXkEyXkFqcGdeQXVyMzQ0MzA0NTM#._V1_UX128_CR0,3,128,176_AL_.jpg
There's a substring of it:
UX128_CR0,3,128,176
This has three important parts:
The first 128 resizes the image by width, keeping ratio
The second 128 controls the container width that the image appears in
176 controls the container height that the image appears in.
So, we can view the structure like this:
UX<image_width>_CR0,3,<container_width>,<container_height>
As an example, to double the image size:
UX256_CR0,3,256,352_AL_.jpg
(Click here to see: https://m.media-amazon.com/images/M/MV5BZWMyYzFjYTYtNTRjYi00OGExLWE2YzgtOGRmYjAxZTU3NzBiXkEyXkFqcGdeQXVyMzQ0MzA0NTM#.V1_UX256_CR0,3,256,352_AL.jpg
Update: Example of how you might do it in Python.
import re
resize_factor = 2 # Image size multiple
url = "https://m.media-amazon.com/images/M/MV5BZWMyYzFjYTYtNTRjYi00OGExLWE2YzgtOGRmYjAxZTU3NzBiXkEyXkFqcGdeQXVyMzQ0MzA0NTM#._V1_UX128_CR0,3,128,176_AL_.jpg"
#
# resize_factor : Image size multiplier (e.g., resize_factor = 2 doubles the image size, positive integer only)
# url : full URL of the image
# return : string of the new URL
#
def getURL(resize_factor, url):
# Regex for pattern matching relevant parts of the URL
p = re.compile(".*UX([0-9]*)_CR0,([0-9]*),([0-9]*),([0-9]*).*")
match = p.search(url)
if match:
# Get the image dimensions from the URL
img_width = str(int(match.group(1)) * resize_factor)
container_width = str(int(match.group(3)) * resize_factor)
container_height = str(int (match.group(4)) * resize_factor)
# Change the image dimensions
result = re.sub(r"(.*UX)([0-9]*)(.*)", r"\g<1>"+ img_width +"\g<3>", url)
result = re.sub(r"(.*UX[0-9]*_CR0,[0-9]*,)([0-9]*)(.*)", r"\g<1>"+ img_width +"\g<3>", result)
result = re.sub(r"(.*UX[0-9]*_CR0,[0-9]*,[0-9]*,)([0-9]*)(.*)", r"\g<1>"+ container_height +"\g<3>", result)
return result
#
# Test
#
print (getURL(resize_factor,url))
Edit: Typo

Python image in `bytes` - get height, width

I'm trying to detect width and height of an image before saving it to the database and S3. The image is in bytes.
This is an example of an image before saved to Django ImageField:
NOTE: I don't want to use ImageFields height_field and width_field as it slows down the server tremendously for some reason so I want to do it manually.
The image is downloaded using requests:
def download_image(url):
r = requests.get(url, stream=True)
r.raw.decode_content = True
return r.content
To get the width/height of an image from a binary string, you would have to try to parse the binary string with an image library. The easiest one for the job would be pillow.
import requests
from PIL import Image
import io
def download_image(url):
r = requests.get(url, stream=True)
r.raw.decode_content = True
return r.content
image_url = "https://picsum.photos/seed/picsum/300/200"
image_data = download_image(image_url)
image = Image.open(io.BytesIO(image_data))
width = image.width
height = image.height
print(f'width: {width}, height: {height}')
width: 300, height: 200

marking box in an image from response request python

import requests
import cv2
frame=cv2.imread('C:\\Users\\aaa\\Downloads\\abc.jpg')
url = 'https://app.nanonets.com/api/v2/ObjectDetection/Model/4729a79f-ab19-4c1b-8fe9'
data = {'file': open('C:\\Users\\aaa\\Downloads\\abc.jpg', 'rb')}
response = requests.post(url, auth=requests.auth.HTTPBasicAuth('S5zsN-yFZJxRH9tMwsaHUCxJg3dZaDWj', ''), files=data)
print (type(response))
print(response)
I uploaded an image for object detection. I got the response like this.
{"message":"Success","result":[{"message":"Success","input":"abc.jpg","prediction":[{"label":"car","xmin":411,"ymin":332,"xmax":585,"ymax":462,"score":0.99097943},{"label":"car","xmin":496,"ymin":170,"xmax":592,"ymax":248,"score":0.96399206},{"label":"car","xmin":223,"ymin":147,"xmax":294,"ymax":202,"score":0.9383388},{"label":"car","xmin":164,"ymin":130,"xmax":230,"ymax":175,"score":0.8968652},{"label":"car","xmin":448,"ymin":489,"xmax":623,"ymax":540,"score":0.8311123}],"page":0,"request_file_id":"5a8549f1-fb2c-487a-83b5-234608b3168b","filepath":"uploadedfiles/4729a79f-ab19-fac0fb807e6d/PredictionImages/53207.jpeg"}]}
I want to make a box in the image with the given coordinates.
import requests
import cv2
import math
from PIL import Image, ImageDraw
import json
frame=cv2.imread('C:\Users\aaa\Downloads\abc.jpg')
url = 'https://app.nanonets.com/api/v2/ObjectDetection/Model/4729a79f-ab19-4c1b-8fe9'
data = {'file': open('C:\Users\aaa\Downloads\abc.jpg', 'rb')}
response = requests.post(url, auth=requests.auth.HTTPBasicAuth('S5zsN-yFZJxRH9tMwsaHUCxJg3dZaDWj', ''), files=data)
predictions = json.loads(response.text)['result'][0]['prediction']
img = Image.open('C:\Users\aaa\Downloads\abc.jpg')
img1 = ImageDraw.Draw(img)
for prediction in predictions:
shape = [(prediction['xmin'], prediction['ymin']), (prediction['xmax'], prediction['ymax'])]
img1.rectangle(shape, fill ="# ffff33", outline ="red")
img.show()

Progress Bar while download file over http with Requests

I need to download a sizable (~200MB) file. I figured out how to download and save the file with here. It would be nice to have a progress bar to know how much has been downloaded. I found ProgressBar but I'm not sure how to incorperate the two together.
Here's the code I tried, but it didn't work.
bar = progressbar.ProgressBar(max_value=progressbar.UnknownLength)
with closing(download_file()) as r:
for i in range(20):
bar.update(i)
I suggest you try tqdm, it's very easy to use.
Example code for downloading with requests library:
from tqdm import tqdm
import requests
url = "http://www.ovh.net/files/10Mb.dat" #big file test
# Streaming, so we can iterate over the response.
response = requests.get(url, stream=True)
total_size_in_bytes= int(response.headers.get('content-length', 0))
block_size = 1024 #1 Kibibyte
progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)
with open('test.dat', 'wb') as file:
for data in response.iter_content(block_size):
progress_bar.update(len(data))
file.write(data)
progress_bar.close()
if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes:
print("ERROR, something went wrong")
The tqdm package now includes a function designed more specifically for this type of situation: wrapattr. You just wrap an object's read (or write) attribute, and tqdm handles the rest; there's no messing with block sizes or anything like that. Here's a simple download function that puts it all together with requests:
def download(url, filename):
import functools
import pathlib
import shutil
import requests
from tqdm.auto import tqdm
r = requests.get(url, stream=True, allow_redirects=True)
if r.status_code != 200:
r.raise_for_status() # Will only raise for 4xx codes, so...
raise RuntimeError(f"Request to {url} returned status code {r.status_code}")
file_size = int(r.headers.get('Content-Length', 0))
path = pathlib.Path(filename).expanduser().resolve()
path.parent.mkdir(parents=True, exist_ok=True)
desc = "(Unknown total file size)" if file_size == 0 else ""
r.raw.read = functools.partial(r.raw.read, decode_content=True) # Decompress if needed
with tqdm.wrapattr(r.raw, "read", total=file_size, desc=desc) as r_raw:
with path.open("wb") as f:
shutil.copyfileobj(r_raw, f)
return path
It seems that there is a disconnect between the examples on the Progress Bar Usage page and what the code actually requires.
In the following example, note the use of maxval instead of max_value. Also note the use of .start() to initialized the bar. This has been noted in an Issue.
The n_chunk parameter denotes how many 1024 kb chunks to stream at once while looping through the request iterator.
import requests
import time
import numpy as np
import progressbar
url = "http://wikipedia.com/"
def download_file(url, n_chunk=1):
r = requests.get(url, stream=True)
# Estimates the number of bar updates
block_size = 1024
file_size = int(r.headers.get('Content-Length', None))
num_bars = np.ceil(file_size / (n_chunk * block_size))
bar = progressbar.ProgressBar(maxval=num_bars).start()
with open('test.html', 'wb') as f:
for i, chunk in enumerate(r.iter_content(chunk_size=n_chunk * block_size)):
f.write(chunk)
bar.update(i+1)
# Add a little sleep so you can see the bar progress
time.sleep(0.05)
return
download_file(url)
EDIT: Addressed comment about code clarity.
EDIT2: Fixed logic so bar reports 100% at completion. Credit to leovp's answer for using the 1024 kb block size.
Also python library enlighten can be used, it is powerful, provides colorful progress bars and correctly works in Linux, Windows.
Below is code + live screen-cast. This code can be run here on repl.it.
import math
import requests, enlighten
url = 'https://upload.wikimedia.org/wikipedia/commons/a/ae/Arthur_Streeton_-_Fire%27s_on_-_Google_Art_Project.jpg?download'
fname = 'image.jpg'
# Should be one global variable
MANAGER = enlighten.get_manager()
r = requests.get(url, stream = True)
assert r.status_code == 200, r.status_code
dlen = int(r.headers.get('Content-Length', '0')) or None
with MANAGER.counter(color = 'green', total = dlen and math.ceil(dlen / 2 ** 20), unit = 'MiB', leave = False) as ctr, \
open(fname, 'wb', buffering = 2 ** 24) as f:
for chunk in r.iter_content(chunk_size = 2 ** 20):
print(chunk[-16:].hex().upper())
f.write(chunk)
ctr.update()
Output (+ ascii-video)
It seems like you're going to need to get the remote file size (answered here) to calculate how far along you are.
You could then update your progress bar while processing each chunk... if you know the total size and the size of the chunk, you can figure out when to update the progress bar.
There is an answer with tqdm.
def download(url, fname):
resp = requests.get(url, stream=True)
total = int(resp.headers.get('content-length', 0))
with open(fname, 'wb') as file, tqdm(
desc=fname,
total=total,
unit='iB',
unit_scale=True,
unit_divisor=1024,
) as bar:
for data in resp.iter_content(chunk_size=1024):
size = file.write(data)
bar.update(size)
Gits: https://gist.github.com/yanqd0/c13ed29e29432e3cf3e7c38467f42f51
Calculating the file size with your already downloaded size would find how far you are. Or you could use tqdm.
For some reason I couldn't get file size with requests when working with zip files, so I used urllib to get it
# A simple downloader with progress bar
import requests
from tqdm import tqdm
import zipfile
from urllib.request import urlopen
url = "https://web.cs.dal.ca/~juanr/downloads/malnis_dataset.zip"
block_size = 1024 #1 Kibibyte
filename = url.split("/")[-1]
print(f"Downloading {filename}...")
site = urlopen(url)
meta = site.info()
# Streaming, so we can iterate over the response.
response = requests.get(url, stream=True)
total_size_in_bytes = int(meta["Content-Length"])
progress_bar = tqdm(total = total_size_in_bytes, unit='iB', unit_scale=True)
with open('test.dat', 'wb') as file:
for data in response.iter_content(block_size):
progress_bar.update(len(data))
file.write(data)
progress_bar.close()
print("Download complete")
print(f"Extracting {filename}...")
zip = zipfile.ZipFile(filename, "r")
zip.extractall()
zip.close()
print("Extracting complete")

Python requests base64 image

I am using requests to get the image from remote URL. Since the images will always be 16x16, I want to convert them to base64, so that I can embed them later to use in HTML img tag.
import requests
import base64
response = requests.get(url).content
print(response)
b = base64.b64encode(response)
src = "data:image/png;base64," + b
The output for response is:
response = b'GIF89a\x80\x00\x80\x00\xc4\x1f\x00\xff\xff\xff\x00\x00\x00\xff\x00\x00\xff\x88\x88"""\xffff\...
The HTML part is:
<img src="{{src}}"/>
But the image is not displayed.
How can I properly base-64 encode the response?
I think it's just
import base64
import requests
response = requests.get(url)
uri = ("data:" +
response.headers['Content-Type'] + ";" +
"base64," + base64.b64encode(response.content))
Assuming content-type is set.
This worked for me:
import base64
import requests
response = requests.get(url)
uri = ("data:" +
response.headers['Content-Type'] + ";" +
"base64," + base64.b64encode(response.content).decode("utf-8"))
You may use the base64 package.
import requests
import base64
response = requests.get(url).content
print(response)
b64response = base64.b64encode(response)
print b64response
Here's my code to send/receive images over Http requests, encoded with base64
Send Request:
# Read Image
image_data = cv2.imread(image_path)
# Convert numpy array To PIL image
pil_detection_img = Image.fromarray(cv2.cvtColor(img_detections, cv2.COLOR_BGR2RGB))
# Convert PIL image to bytes
buffered_detection = BytesIO()
# Save Buffered Bytes
pil_detection_img.save(buffered_detection, format='PNG')
# Base 64 encode bytes data
# result : bytes
base64_detection = base64.b64encode(buffered_detection.getvalue())
# Decode this bytes to text
# result : string (utf-8)
base64_detection = base64_detection.decode('utf-8')
base64_plate = base64_plate.decode('utf-8')
data = {
"cam_id": "10415",
"detecion_image": base64_detection,
}
Recieve Request
content = request.json
encoded_image = content['image']
decoded_image = base64.b64decode(encoded_image)
out_image = open('image_name', 'wb')
out_image.write(decoded_image)

Categories

Resources