Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Help with photos module and http post?
-
Hello Everyone,
I am currently messing around with the Kairos API and am trying to use Pythonista to take a new photo on my iPad and then upload that photo to the Kairos enroll API. I am able to get this to work fine with a URL image but for the life of me I am unable to get this to work by taking a photo with the photos module. From my understanding the photos module returns a PIL Image and I think I need to base64 encode that before uploading to the Kairos API??
Here is my code without using the photos module:
#import photos import requests #img = photos.capture_image() url = "https://api.kairos.com/enroll" values = """ { "image": "URL for image", "subject_id": "test", "gallery_name": "test" } """ headers = { 'Content-Type': 'application/json', 'app_id': '********', 'app_key': '************************' } request = requests.post(url, data=values, headers=headers) response = request.content print(response)
Im hoping that someone can help me out by showing me what I need to do to be able to accomplish this task. Any help is greatly appreciated.
Thank you in advance,
Colin
-
A common approach is to use BytesIO:
import io with io.BytesIO() as output: img.save(output) contents = output.getvalue()
You might need to then pass contents through base64.b64encode
-
Thanks jonB
Its interesting because I have tried that as well and am not having good results. Maybe I just dont understand how to use io well enough yet...
-
@inzel, what do the Kairos API docs say about uploaded image formats, sizes etc., any gotchas there?
-
Here is the only real info I have from their docs:
https://www.kairos.com/docs/api/
POST /enroll
Takes a photo, finds the faces within it, and stores the faces into a gallery you create.
To enroll someone into a gallery, all you need to do is submit a JPG or PNG photo. You can submit the photo either as a publicly accessible URL, Base64 encoded photo or as a file upload.-inzel
-
@inzel, ok, thanks. Can you share the relevant piece of the actual code where you are trying to upload the image?
-
The code is basically what I put in my original post. I have tried many many different things but havent been saving my code each time as I havent fully understood the modules. I guess I should just comment it all out in the future instead of deleting it. My main question is how I could take the image obtained from photos.capture_image() and then base64 encode it and send it in POST data.
If you have any thoughts on that I would love to hear about it :) Or if you have any thoughts on another way of accomplising the same task that would be great as well.
Thank you in advance!
-inzel
-
so, did you try the bytesio code, followed by b64encode? Post that completed attempt, then we can work from there. You might need to pass that through .decode('ascii') after that. you might need json= instead of data=.
I found a complete python api:
https://github.com/ffmmjj/kairos-face-sdk-python/blob/master/kairos_face/enroll.py
which uses those two other modifications I mentioned (they read the file directly, but the important thing is just getting the bytes out into b64encode)
-
-
-
I am trying to use bytesio and base64 but cant get past the img.save line:
import photos import requests import io import base64 #img = photos.capture_image() with io.BytesIO() as output: img = photos.capture_image() img.save(output) contents = output.getvalue() image = base64.b64encode(contents) url = "https://api.kairos.com/enroll``` Error is: Traceback (most recent call last): File "/private/var/mobile/Containers/Shared/AppGroup/2D8E43AB-E263-4AE8-9F57-E62CCC11779D/Pythonista3/Documents/Kairos/kairos_upload.py", line 10, in <module> img.save(output) File "/var/containers/Bundle/Application/3C9A09E3-8A1E-49E7-956B-A8E46A817D5A/Pythonista3.app/Frameworks/Py2Kit.framework/pylib/site-packages/PIL/Image.py", line 1697, in save format = EXTENSION[ext] KeyError Appears that the save function requires me to have an extension. I then tried another angle and am getting a new error:
img = photos.capture_image()
contents = io.BytesIO(img)
binary_data = contents.getvalue()
image = base64.b64encode(binary_data)```Error is:
Traceback (most recent call last):
File "/private/var/mobile/Containers/Shared/AppGroup/2D8E43AB-E263-4AE8-9F57-E62CCC11779D/Pythonista3/Documents/Kairos/kairos_upload.py", line 8, in <module>
contents = io.BytesIO(img)
TypeError: 'Image' does not have the buffer interface -
@cvp Thanks! I will look in to that as well
-
@inzel if tu save a PIL image to a variable, you have to specify the format
img.save(output,'JPG')
-
I tried that as well as:
img.save(output, format = ‘JPG’)
And I get errors each time:
img.save(output, ‘JPG’) :
Traceback (most recent call last):
File "/private/var/mobile/Containers/Shared/AppGroup/2D8E43AB-E263-4AE8-9F57-E62CCC11779D/Pythonista3/Documents/Kairos/kairos_upload.py", line 9, in <module>
img.save(output,'JPG')
File "/var/containers/Bundle/Application/3C9A09E3-8A1E-49E7-956B-A8E46A817D5A/Pythonista3.app/Frameworks/Py2Kit.framework/pylib/site-packages/PIL/Image.py", line 1704, in save
save_handler = SAVE[format.upper()]
KeyError: 'JPG'img.save(output, format = ‘JPG’) :
Traceback (most recent call last):
File "/private/var/mobile/Containers/Shared/AppGroup/2D8E43AB-E263-4AE8-9F57-E62CCC11779D/Pythonista3/Documents/Kairos/kairos_upload.py", line 9, in <module>
img.save(output, format = 'JPG')
File "/var/containers/Bundle/Application/3C9A09E3-8A1E-49E7-956B-A8E46A817D5A/Pythonista3.app/Frameworks/Py2Kit.framework/pylib/site-packages/PIL/Image.py", line 1704, in save
save_handler = SAVE[format.upper()]
KeyError: 'JPG'Maybe my syntax is wrong?
-
@inzel sorry img.save(output,'JPEG') is ok
-
Ah perfect. That part works now.
with io.BytesIO() as output: img = photos.capture_image() img.save(output,'JPEG') contents = output.getvalue() image = base64.b64encode(contents)
I feel we are very close. I believe the final step now is determining the proper syntax to POST the payload. This would be much easier if I was able to use wireshark or another packet capture tool to see how the POST looks as its being sent but I cant do that on my iPad. This is what I am trying for my payload line but the syntax is incorrect:
payload = '{'"image": + image + "',"' + '\n' + '"subject_id": "test" + ","' + '\n' + '"gallery_name": "test"'}'
I need it to look like this when its sent:
{
“image”: image,
“subject_id”: “test”,
“gallery_name”:”test”
}My apologies for all the new guy questions. I really appreciate all the help you guys have provided me so far. Im learning...
-
I got it to work!
import photos import requests import io import base64 import json with io.BytesIO() as output: img = photos.capture_image() img.save(output,'JPEG') contents = output.getvalue() image = base64.b64encode(contents) url = "https://api.kairos.com/enroll" values = { 'image': image, 'subject_id': 'test', 'gallery_name': 'test' } headers = { 'Content-Type': 'application/json', 'app_id': '*********', 'app_key': '*************************' } request = requests.post(url, data=json.dumps(values), headers=headers) response = request.content print(response)``` Thanks everyone!
-
@inzel 👍🍾
-
I decided to clean it up a bit and use some functions. I havent added my comments yet but here is a fully working solution:
import photos import requests import io import base64 import json img = photos.capture_image() def getPhoto(): with io.BytesIO() as output: img.save(output, 'JPEG') contents = output.getvalue() image = base64.b64encode(contents) return image def enrollPhoto(): subject_id = raw_input("Hello, What is your name: ? ") print("Thank you " + subject_id + "." + " Analyzing...") image = getPhoto() url = "https://api.kairos.com/enroll" values = { 'image': image, 'subject_id': subject_id, 'gallery_name': subject_id } headers = { 'Content-Type': 'application/json', 'app_id': '***********', 'app_key': '****************************' } r = requests.post(url, data=json.dumps(values), headers = headers) parsed_json = json.loads(r.content) attr = parsed_json['images'][0]['attributes'] img.show() print(json.dumps(attr, indent=2)) enrollPhoto()
Just need to put in your actual app_id and app_key. Should work right away. My next step will be getting a simple interface built and then comparing the pic of the user to existing pics of the same user to determine whether or not they gain access. Something like that anyways. Turned out to be a fun endeavor!
-
fwiw,
requests
lets you use req.json() rather than json.loads(req.contents). also, you can use json=values instead of json.dumps(values) in the request.