【问题标题】:Should I merge images in memory (.py) or in view (HTML)?我应该在内存(.py)还是视图(HTML)中合并图像?
【发布时间】:2011-09-26 08:40:39
【问题描述】:

我的facebook app 让用户上传一张图片,选择图片是什么(眼睛、鼻子、嘴巴或其他身体部位),然后可以通过按类别选择三个随机图片进行组合,效果很好,代码看起来还可以并且可读性虽然不是很高级:

class CyberFazeHandler(BaseHandler):

    def get_random_image(self, category):
        fileinfos = FileInfo.all().filter("category =", category)
        return fileinfos[random.randint(0, fileinfos.count()-1)] 

    def get(self):
        eyes_image = self.get_random_image(category="eyes")
    nose_image = self.get_random_image(category="nose")
    mouth_image = self.get_random_image(category="mouth")
        eyes_data = None
        try:
        eyes_data = blobstore.fetch_data(eyes_image.blob.key(), 0, 50000)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find eyes data for file '+str(eyes_image.key().id())+' (' + unicode(e) + u')')

        eyes_img = None

        try:
            eyes_img = images.Image(image_data=eyes_data)

...现在我只获取 3 张随机图像,然后在模板中组合:

<a href="/file/{{eyes_image.key.id}}"><img src="{{eyes_url}}"></a><br>
<a href="/file/{{nose_image.key.id}}"><img src="{{nose_url}}"></a><br>
<a href="/file/{{mouth_image.key.id}}"><img src="{{mouth_url}}"></a>

是否可以通过发送一张将三张图片合二为一的合成图片来改善这种情况?其优点是图像上的所有内容都将同时加载,并且如果下次出现随机化结果时已经保存,它将已经保存。你怎么看?

谢谢(应用程序是apps.facebook.com/cyberfaze,您可以查看我为娱乐和学习而做的)

整个班级是

class CyberFazeHandler(BaseHandler):

    def get_random_image(self, category):
        fileinfos = FileInfo.all().filter("category =", category)
        return fileinfos[random.randint(0, fileinfos.count()-1)] #optimize

    def get(self):
        eyes_image = self.get_random_image(category="eyes")
    nose_image = self.get_random_image(category="nose")
    mouth_image = self.get_random_image(category="mouth")
        eyes_data = None
        try:
        eyes_data = blobstore.fetch_data(eyes_image.blob.key(), 0, 50000)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find eyes data for file '+str(eyes_image.key().id())+' (' + unicode(e) + u')')

        eyes_img = None

        try:
            eyes_img = images.Image(image_data=eyes_data)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find eyes img for file '+str(eyes_image.key().id())+' (' + unicode(e) + u')')


        nose_data = None
        try:
            nose_data = blobstore.fetch_data(nose_image.blob.key(), 0, 50000)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find nose data for file '+str(nose_image.key().id())+' (' + unicode(e) + u')')


        nose_img = None

        try:
            nose_img = images.Image(image_data=nose_data)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find nose img for file '+str(nose_image.key().id())+' (' + unicode(e) + u')')


        mouth_data = None
        try:
        mouth_data = blobstore.fetch_data(mouth_image.blob.key(), 0, 50000)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find mouth data for file '+str(eyes_image.key().id())+' (' + unicode(e) + u')')


        mouth_img = None

        try:
            mouth_img = images.Image(image_data=mouth_data)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find mouth img for file '+str(mouth_image.key().id())+' (' + unicode(e) + u')')


    minimum = min(int(eyes_img.width), int(nose_img.width), int(mouth_img.width))

    eyes_url = images.get_serving_url(str(eyes_image.blob.key()), size=minimum)
    nose_url = images.get_serving_url(str(nose_image.blob.key()), size=minimum)
    mouth_url = images.get_serving_url(str(mouth_image.blob.key()), size=minimum)

        self.render(u'cyberfaze', minimum=minimum, eyes_image=eyes_image, eyes_url=eyes_url, nose_image=nose_image, nose_url=nose_url, mouth_image=mouth_image, mouth_url=mouth_url, form_url = blobstore.create_upload_url('/upload'),)

重写后它的工作方式如下:

class CyberFazeHandler(BaseHandler):

    def get_random_image(self, category):

        q = FileInfo.all()
        q.filter('category =', category)
        q.filter('randomvalue >=', random.random())
        return q.get()

    def get_random_image_legacy(self, category):
        fileinfos = FileInfo.all().filter('category =', category)
        return fileinfos[random.randint(0, fileinfos.count() - 1)]

    def get(self):

        eyes_image = self.get_random_image(category='eyes')
    if not eyes_image:
       logging.debug("getting eyes failed, trying legacy method")
           eyes_image = self.get_random_image_legacy(category='eyes')
        nose_image = self.get_random_image(category='nose')
    if not nose_image:
           nose_image = self.get_random_image_legacy(category='nose')

        mouth_image = self.get_random_image(category='mouth')
    if not mouth_image:
           mouth_image = self.get_random_image_legacy(category='mouth')

        eyes_data = None
        try:
            eyes_data = blobstore.fetch_data(eyes_image.blob.key(), 0,
                    50000)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find eyes data for file '
                              + str(eyes_image.key().id()) + ' ('
                             + unicode(e) + u')')

        eyes_img = None

        try:
            eyes_img = images.Image(image_data=eyes_data)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find eyes img for file '
                              + str(eyes_image.key().id()) + ' ('
                             + unicode(e) + u')')

        nose_data = None
        try:
            nose_data = blobstore.fetch_data(nose_image.blob.key(), 0,
                    50000)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find nose data for file '
                              + str(nose_image.key().id()) + ' ('
                             + unicode(e) + u')')

        nose_img = None

        try:
            nose_img = images.Image(image_data=nose_data)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find nose img for file '
                              + str(nose_image.key().id()) + ' ('
                             + unicode(e) + u')')

        mouth_data = None
        try:
            mouth_data = blobstore.fetch_data(mouth_image.blob.key(),
                    0, 50000)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find mouth data for file '
                              + str(eyes_image.key().id()) + ' ('
                             + unicode(e) + u')')

        mouth_img = None

        try:
            mouth_img = images.Image(image_data=mouth_data)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find mouth img for file '
                              + str(mouth_image.key().id()) + ' ('
                             + unicode(e) + u')')

        minimum = min(int(eyes_img.width), int(nose_img.width),
                      int(mouth_img.width))

        eyes_url = images.get_serving_url(str(eyes_image.blob.key()),
                size=minimum)
        nose_url = images.get_serving_url(str(nose_image.blob.key()),
                size=minimum)
        mouth_url = images.get_serving_url(str(mouth_image.blob.key()),
                size=minimum)

        self.render(
            u'cyberfaze',
            minimum=minimum,
            eyes_image=eyes_image,
            eyes_url=eyes_url,
            nose_image=nose_image,
            nose_url=nose_url,
            mouth_image=mouth_image,
            mouth_url=mouth_url,
            form_url=blobstore.create_upload_url('/upload'),
            )

【问题讨论】:

    标签: python facebook google-app-engine image-processing random


    【解决方案1】:

    哪个更有效取决于它的使用方式。如果用户将加载大量此类混搭,将它们作为单独的图像发送更有意义,因为浏览器缓存的图像将更少(a+b+c 图像而不是 a*b*c)。

    但是,您的代码存在更严重的性能问题:

    def get_random_image(self, category):
        fileinfos = FileInfo.all().filter("category =", category)
        return fileinfos[random.randint(0, fileinfos.count()-1)] 
    

    每次调用这个函数,它都会进行一次计数操作,O(n) 与FileInfo 实体的数量,然后执行一个偏移量查询,即O(n) 与偏移量。这是极其缓慢和低效的,并且会随着图像数量的增加而变得更多。

    如果您希望图像集很小(少于几千个)并且相当稳定,只需将它们存储在代码中,这将比任何其他选项更快。如果集合更大,或者在运行时发生变化,则为每个实体分配一个介于 0 和 1 之间的随机值,并使用这样的查询来检索随机选择的一个:

    q = FileInfo.all()
    q.filter('category =', category)
    q.filter('random >=', random.random())
    return q.get()
    

    【讨论】:

      猜你喜欢
      • 2014-11-04
      • 2011-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多