Libvips: problemas de rendimiento de la API web

Creado en 19 ene. 2018  ·  5Comentarios  ·  Fuente: libvips/libvips

Hola,

Quiero usar la API web para pyvips.
Pero realmente mal desempeño. ¿Dónde cometo errores?

Mi código está siguiendo;

hola.py

from flask import Flask
from Image import ImageTransform
from flask import request
from flask import send_file
import io

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

@app.route("/image")
def image():
    image_value = request.args.get('image')
    i = ImageTransform(image_value)
    i.set_transform()
    a = i.image.write_to_buffer('.jpeg')
    return send_file(io.BytesIO(a), mimetype='image/jpg')

Image.py

import pyvips
import math

class ImageTransform(object):
    image = None

    def __init__(self, file_name):
        self.image = pyvips.Image.new_from_file(file_name, access='sequential')

    def set_resize_transform(self, width, height):
        im = self.image
        mem = im.write_to_buffer('.jpeg[Q=80]')
        im = pyvips.Image.thumbnail_buffer(mem, width, height=height)

        im = im.bandjoin(255)
        im = im.gravity("centre", width, height,
                            extend="background",
                            background=[244, 244, 244, 255])
        self.image = im                            
        pass
    def set_ratio_and_watermark_transform(self):
        im = self.image
        # ##### ######
        # Trigonometry: Tangent = Opposite / Adjacent
        tangent = im.height/im.width
        # convert arctangent to degrees
        angle = math.atan(tangent)*(180/math.pi);

        water_mark_x = 140
        water_mark_y = 140
        water_mark_len = 16
        # a^2 = b^2 + c^2 ; a = sqrt(b^2 + c^2)
        half_hypotenuse = math.sqrt(im.height*im.height + im.width*im.width)/2;
        font_size = int(math.hypot(im.height, im.width)/math.hypot(water_mark_x, water_mark_y)*(4 + int(water_mark_len/2)))

        text = pyvips.Image.text("text text text", font = "Futura Medium", align='centre', width = 500, dpi = (font_size*4))
        text = text.linear(0.3, 0)

        text = text.similarity(angle=angle)

        x = (im.width-text.width)/2
        y = (im.height-text.height)/2

        text = text.embed(x, y, text.width + x, text.height + y, extend="copy")

        w = im.width if text.width > im.width else text.width
        h = im.height if text.height > im.height else text.height

        im = text.ifthenelse(255, im, blend=True)      
        self.image = im

    def set_transform(self, type=int):
        self.set_ratio_and_watermark_transform()
        self.set_resize_transform(600, 450)

    def write_image(self,dest_name):
        self.image.write_to_file(dest_name)

`` bash
FLASK_APP = hello.py matraz ejecutar

```bash
ab -c 10 -n 10 http://54.229.246.74/image\?image\=foto.jpeg
question

Comentario más útil

Creo que agregaría la marca de agua así:

# in libvips 8.6, you can get text to automatically size to fill a rectangle
text = pyvips.Image.text("text text text", 
                         font="Futura Medium", align="centre", 
                         width=300, height=300)  

# scale down brightness, then back to 8 bit ... this will avoid float arithmetic
# for the rotate/expand/ifthenelse
text = (text * 0.3).cast("uchar")

tangent = float(im.width) / im.height
angle = math.atan(tangent) * (180 / math.pi)
text = text.similarity(angle=angle)
text = text.gravity("centre", target_width, target_height)

im = text.ifthenelse(255, im, blend=True) 

Así que eso es usar la nueva función "ajustar el tamaño del texto al cuadro" en 8.6, usando x * 0.3 lugar de linear (hacen lo mismo, la sobrecarga del operador es más fácil de leer), manteniendo el texto como 8 bits para evitar que flote más tarde, y usar gravity para hacer que embed un poco más simple.

Todos 5 comentarios

Hola @volkan ,

Reorganizaría su canalización a algo como:

  1. Use thumbnail para abrir la imagen y reducir el tamaño en una sola operación
  2. Agregar la superposición de la marca de agua
  3. Finalmente, use gravity para agregar el fondo

Te daré un ejemplo.

Aquí hay un programa de prueba que ejecuta su código y una posible nueva canalización. Cambié la línea tangente en su versión a:

        tangent = float(im.width) / im.height

Pero por lo demás inalterado.

import time
import sys
import math
import pyvips

from Image import ImageTransform

start = time.time()
i = ImageTransform(sys.argv[1])
i.set_transform()
i.write_image(sys.argv[2])
end = time.time()
print "ImageTransform() took ", end - start

start = time.time()

target_width = 600
target_height = 450         

# efficiently load and downsize in one operation
im = pyvips.Image.thumbnail(sys.argv[1], target_width, height=target_height)

# watermark
tangent = float(im.width) / im.height
angle = math.atan(tangent) * (180 / math.pi)
water_mark_x = 140
water_mark_y = 140
water_mark_len = 16
half_hypotenuse = math.sqrt(im.height*im.height + im.width*im.width)/2;
font_size = int(math.hypot(im.height, im.width)/math.hypot(water_mark_x, water_mark_y)*(4 + int(water_mark_len/2)))
text = pyvips.Image.text("text text text", font = "Futura Medium", align='centre', width = 500, dpi = (font_size*4))
text = text.linear(0.3, 0)
text = text.similarity(angle=angle)
x = (im.width - text.width) / 2
y = (im.height - text.height) / 2
text = text.embed(x, y, text.width + x, text.height + y, extend="copy")
w = im.width if text.width > im.width else text.width
h = im.height if text.height > im.height else text.height
im = text.ifthenelse(255, im, blend=True)  

# add alpha and margins
im = im.bandjoin(255)
im = im.gravity("centre", target_width, target_height,
                    extend="background",
                    background=[244, 244, 244, 255])

im.write_to_file(sys.argv[2])

end = time.time()

print "after revision, took ", end - start

En esta computadora portátil con una imagen de 6k x 4k, veo:

$ python volkan.py ~/pics/theo.jpg x.jpg
ImageTransform() took  0.490525960922
after revision, took  0.0774891376495

Podrías hacer que tu código de marca de agua sea un poco más simple, lo intentaré.

Creo que agregaría la marca de agua así:

# in libvips 8.6, you can get text to automatically size to fill a rectangle
text = pyvips.Image.text("text text text", 
                         font="Futura Medium", align="centre", 
                         width=300, height=300)  

# scale down brightness, then back to 8 bit ... this will avoid float arithmetic
# for the rotate/expand/ifthenelse
text = (text * 0.3).cast("uchar")

tangent = float(im.width) / im.height
angle = math.atan(tangent) * (180 / math.pi)
text = text.similarity(angle=angle)
text = text.gravity("centre", target_width, target_height)

im = text.ifthenelse(255, im, blend=True) 

Así que eso es usar la nueva función "ajustar el tamaño del texto al cuadro" en 8.6, usando x * 0.3 lugar de linear (hacen lo mismo, la sobrecarga del operador es más fácil de leer), manteniendo el texto como 8 bits para evitar que flote más tarde, y usar gravity para hacer que embed un poco más simple.

@jcupitt sus ejemplos son muy útiles. Gracias.

¡Bien, cerraré!

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

binarykitchen picture binarykitchen  ·  3Comentarios

harukizaemon picture harukizaemon  ·  4Comentarios

felixbuenemann picture felixbuenemann  ·  4Comentarios

revathi-murali picture revathi-murali  ·  3Comentarios

AKlein920 picture AKlein920  ·  3Comentarios