from PIL import Image
from bson import Binary
img = Image.open('test.jpg')
img = Binary(img)
throws an error stating TypeError : data must be an instance of bytes
Why does this happen? And how to resolve this to store the img to MongoDB?
As long as the document doesn't exceed 16MB standard bson is fine, otherwise gridfs should be used. The example below shows how an image can be inserted and read back from a mongodb.
insert_image.py
from pymongo import MongoClient
from PIL import Image
import io
client = MongoClient()
db = client.testdb
images = db.images
im = Image.open("./image.jpg")
image_bytes = io.BytesIO()
im.save(image_bytes, format='JPEG')
image = {
'data': image_bytes.getvalue()
}
image_id = images.insert_one(image).inserted_id
read_image.py
from pymongo import MongoClient
from bson.binary import Binary
from PIL import Image
import io
import matplotlib.pyplot as plt
client = MongoClient()
db = client.testdb
images = db.images
image = images.find_one()
pil_img = Image.open(io.BytesIO(image['data']))
plt.imshow(pil_img)
plt.show()
You need to convert the image into a Byte array. You can do this as follows,
from PIL import Image
from bson import Binary
img = Image.open('test.jpg')
imgByteArr = io.BytesIO()
img.save(imgByteArr, format='PNG')
imgByteArr = imgByteArr.getvalue()
You can try to save imgByteArr into mongo
OR
You can convert image into string and then store it in mongo:
import base64
with open("test.jpg", "rb") as imageFile:
str = base64.b64encode(imageFile.read())
//store str in mongo
To get back image
with open("test2.jpg", "wb") as fimage:
fimage.write(str.decode('base64'))
Related
Hi I’ve bought the dispay pack2 (https://shop.pimoroni.com/products/pico-display-pack-2-0?variant=39374122582099) and am trying to display an image. If I download the image and put it on the pi pico w then the image displays OK. I’m trying to get the image to be downloaded from a URL and displayed but am getting
MemoryError: memory allocation failed, allocating 21760 bytes
I’m new to this sort of coding and am struggling to see what I’m doing wrong. here is my full py code
`
import network
import urequests
import time
import picographics
import jpegdec
from pimoroni import Button
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("SSID","password")
time.sleep(5)
print(wlan.isconnected())
display = picographics.PicoGraphics(display=picographics.DISPLAY_PICO_DISPLAY_2, rotate=0)
display.set_backlight(0.8)
# Create a new JPEG decoder for our PicoGraphics
j = jpegdec.JPEG(display)
# Open the JPEG file
#j.open_file("squid.jpg")
# Decode the JPEG
#j.decode(0, 0, jpegdec.JPEG_SCALE_FULL)
if wlan.isconnected():
res = urequests.get(url='https://squirrel365.io/tmp/squid.jpg')
j.open_RAM(memoryview(res.content))
# Decode the JPEG
j.decode(0, 0, jpegdec.JPEG_SCALE_FULL)
# Display the result
display.update()
`
Any ideas?
Kedge
I've tested and can get plain text back from the URL, as soon as I try and get an image I get the memory error
You're not doing anything "wrong"; you're just working with a device that has very limited resources. What if you re-arrange your code to perform the fetch before initializing any graphics resources, write the data to a file, and then have the jpeg module read it from disk? Something like:
import jpegdec
import network
import picographics
import time
import urequests
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("SSID","password")
while not wlan.isconnected():
print('waiting for network')
time.sleep(1)
res = urequests.get(url='https://squirrel365.io/tmp/squid.jpg')
with open('squid.jpg', 'wb') as fd:
fd.write(res.content)
display = picographics.PicoGraphics(display=picographics.DISPLAY_PICO_DISPLAY_2, rotate=0)
display.set_backlight(0.8)
# Create a new JPEG decoder for our PicoGraphics
j = jpegdec.JPEG(display)
# Open the JPEG file
j.open_file("squid.jpg")
# Decode the JPEG
j.decode(0, 0, jpegdec.JPEG_SCALE_FULL)
# Display the result
display.update()
You can sometimes free up additional memory by adding an explicit garbage collection to your code:
import gc
.
.
.
with open('squid.jpg', 'wb') as fd:
fd.write(res.content)
gc.collect()
I am writing an entire Pandas DataFrame as bytestream into a flat file and into a Mongo Database, e.g here
import logging
from io import BytesIO
import pandas as pd
import numpy as np
from pymongo import MongoClient
from uuid import uuid4
logger = logging.getLogger(__name__)
logging.basicConfig(format='%(asctime)s %(levelname)s - %(message)s', level=logging.INFO)
MONGODB_SETTINGS = {"Local": {'host': 'host.docker.internal',
'port': 27017}}
if __name__ == '__main__':
logger.info("Start")
frame = pd.DataFrame(columns=list("ABCDE"), data=np.random.randn(300_000, 5))
logger.info("Constructed Frame (object)")
name = str(uuid4())
bytestream = frame.to_parquet()
post = {"frame": bytestream, "name": name}
logger.info("Dictionary constructed")
with open('data/tmp/output', 'wb') as file:
file.write(bytestream)
logger.info("Bytestrem written to disk")
for key, settings in MONGODB_SETTINGS.items():
logger.info(50 * "-")
logger.info(key)
with MongoClient(**settings) as client:
db = client.capture
collection = db.frame
logger.info("Start writinng into Database")
collection.insert_one(post)
logger.info("Object written to Database")
# read the frame back from database
x = collection.find_one({"name": name})
with BytesIO(x["frame"]) as buffer:
frame_out = pd.read_parquet(buffer)
logger.info("Object read from Database")
pd.testing.assert_frame_equal(frame, frame_out)
logger.info(50 * "-")
It takes like 0.1s to write the file where as it takes 3s to write into the Mongo Database. The database is hosted on my local computer and runs within the standard Mongo image. Am I missing something. Is that loss of speed normal?
With code as ineffecient as that, yes.
import boto3
import pandas as pd
import io
def lambda_handler(event, context):
if event:
s3_client = boto3.client('s3')
bucket = event['Records'][0]['s3']['bucket']['name']
key = event['Records'][0]['s3']['object']['key']
file_obj = s3_client.get_object(Bucket=bucket,Key=key)
file_content = file_obj['Body'].read()
b = io.BytesIO(file_content)
df = pd.read_excel(b)
print(df)
I am trying to upload excel sheet data from s3 to amazon rds (Postgres). The above code is what I have to extract data from s3. How can I upload the data from here to postgres, Please Help.
I added a chart in docx, and I hope I can edit the data to change histogram bins length.
How can I do it?
#scanny This is the code I tried, and show me error is
chart.replace_data(chart_data) AttributeError: 'module' object has no
attribute 'replace_data'
import docx
import os
import sys
import csv
import datetime
import time
import pptx
from pptx import chart
from pptx.chart import data
from pptx.chart.data import CategoryChartData
CURRENT_DIR = os.path.dirname(os.path.abspath(sys.argv[0]))
docxFilePath = os.path.join(CURRENT_DIR,'sample.docx')
chart_data = CategoryChartData()
chart_data.categories = ['East', 'West', 'Midwest']
chart_data.add_series('Series 1', (19.2, 21.4, 16.7))
chart.replace_data(chart_data)
filename ='test.docx'
filepath = os.path.join(r'C:\Users\Administrator\Desktop\python test\update_test', filename)
doc.save(filepath)
Charts in python-pptx are updated by populating a new ChartData object and passing it to chart.replace_data:
from pptx.chart.data import CategoryChartData
chart_data = CategoryChartData()
chart_data.categories = ['East', 'West', 'Midwest']
chart_data.add_series('Series 1', (19.2, 21.4, 16.7))
chart.replace_data(chart_data)
I'm storing image files using GridFS. But I don't know how to retrieve those files using PyMongo and display them on web page.
#post('/blog')
def blog_post():
blog_title = request.forms.get('title')
blog_content = request.forms.get("content")
file_post = request.files.get('image_file')
if file_post and file_post.file:
raw = file_post.file.read()
filename = file_post.filename
DBNAME = "te3371db"
db = connection[DBNAME]
fs = gridfs.GridFS(db)
fs.put(raw,filename=filename)