5

I use opencv to crop images and I'd like to save them to the models, I load the file directly to computeLogoFromMemoryFILE where it is processed, from there how can I save the image to TempImage model?

views.py:

form = myForm(request.FILES)
if form.is_valid():
    cropped_image = computeLogoFromMemoryFILE(request.FILES.get('logo'))
    # ...
    temp_image = TempImage.objects.create(image=?)

cv2:

# (np == numpy)
def computeLogoFromMemoryFILE(logo):
    logo.seek(0)
    image = cv2.imdecode(np.fromstring(logo.read(), np.uint8), cv2.IMREAD_UNCHANGED)
    cropped_img = crop_image(image)

cropped_image variable is an opencv array :

array([[ 52, 218, 255],
    [ 52, 218, 255],
    [ 52, 218, 255],
    ...,
    [ 52, 218, 255],
    [ 52, 218, 255],
    [ 52, 218, 255]]...], dtype=uint8)

How should I proceed?

Horai Nuri
  • 5,358
  • 16
  • 75
  • 127
  • If the image is big, you should prefer uploading it separately and only storing the link to it in your database. If it's fairly small, you can convert your np array into a string and store it - convert it back when you want to read it. I haven't worked with django all that much, but I guess you can store images as blobs too. – Zeokav Mar 08 '18 at 10:41
  • @Zeokav Of course only the link will be stored, since the images are on AWS, but I don't understand how I can make the transition from the opencv array to the new dbb record. The images are also fairly small (less than 1MB). – Horai Nuri Mar 08 '18 at 10:49
  • I guess you are familiar with storing and accessing objects in AWS (s3?), since you say that the images are stored on AWS. In general you convert the image to bytes string, upload this file object to AWS and then store key (usually a filename) in your database, because you'll be accessing files with this key. I suggest you update your question, because this is really a question about uploading files to AWS. The Django part is basically the simplest thing here. – Borut Mar 08 '18 at 12:08

2 Answers2

4

In Django everytime you needs to manipulate uploaded files, similar images and set these to Model-Fields you must use Django File class, you can doing similar this code:

from django.core.files import File

def my_view(request):
    ...
    form = myForm(request.FILES)

    if form.is_valid():
        temp_image = myForm.save(commit=False)
        cropped_image = computeLogoFromMemoryFILE(request.FILES.get('logo'))
        with open('path/of/cropped_image.png', 'rb') as destination_file:
            temp_image.image.save('dest.png', File(destination_file), save=False)
        temp_image.save()
    ...

Note: After setup file to model field this file cloned on the MEDIA_ROOT, it is better that you remove old image or use BytesIO instead of using file to store manipulated image.

M.javid
  • 6,387
  • 3
  • 41
  • 56
4

Model:

class ImageModel(models.Model):
    image = models.FileField(upload_to='images/')

View:

from django.core.files.base import ContentFile

def index(request):

    ...
    ret, buf = cv2.imencode('.jpg', cropped_image) # cropped_image: cv2 / np array
    content = ContentFile(buf.tobytes())

    img_model = ImageModel()
    img_model.image.save('output.jpg', content)

ContentFile support bytes and string: https://docs.djangoproject.com/en/3.1/ref/files/file/#django.core.files.base.ContentFile

hungtran273
  • 1,180
  • 9
  • 11