在AB测试中尝试进行面部蒙太奇

abface

A和B,你更喜欢哪个面孔?

进行A/B测试是指准备了两种不同模式的网页,让真实用户使用并比较其效果的测试。

展示微妙不同版本的页面给数千名访问网站的用户中的一位,然后比较点击率等与通常版本的差异。如果结果比通常版本好,就采用它作为新的通常版本,并进行进一步的微小改动来进行测试…

A/B测试,大致上是这种方法。
这个方法也因奥巴马总统在选举中使用过而出名。

这个与针对大规模用户的一般A/B测试有一点不同,但是通过面部蒙太奇试图做出类似A/B测试的东西就是这个。

AB face是一个在线的网页应用程序的网址,可以通过http://xiidec.appspot.com/abface.html访问。

点击A或B中喜欢的脸。
然后选中的脸将保留,并提供新的选择。
通过连续选择,理想的脸将逐渐形成。

机构组织

那么,现在我们来看一下实际内容吧。
只有150行而已。是的,我们能够做到。

    1. 准备一些眉毛、眼睛、鼻子、嘴巴的图像并给它们编号。

 

    随机选择每个部分。

首先是服务器端。使用Python语言编写的代码。

翻译为中文后的句子如下:咖喱汁

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import webapp2
import os
import random
from google.appengine.ext.webapp import template
from google.appengine.api import memcache

class Abface(webapp2.RequestHandler):
    def get(self):
        self.draw()

    def post(self):
        if not self.request.get('choice') is None and self.request.get('choice')!="":
            memcache.set("face",[int(i) for i in  self.request.get('choice').split(",")], 3600)
            memcache.set("sel",self.request.get('sel'), 3600)
        self.draw()

    def draw(self):
        face1 = self.makeface()
        face2=[i for i in face1]
        r=random.randint(0,3)
        face2[r] = int(random.choice("12345".replace(str(face2[r]), "")))
        if memcache.get("sel")=="B":
            face1,face2=face2,face1
        template_values={
            'brow1':'brow_' + str(face1[0]) + '.jpg',
            'eye1':'eye_' + str(face1[1]) + '.jpg',
            'nose1':'nose_' + str(face1[2]) + '.jpg',
            'mouth1':'mouth_' + str(face1[3]) + '.jpg',
            'brow2':'brow_' + str(face2[0]) + '.jpg',
            'eye2':'eye_' + str(face2[1]) + '.jpg',
            'nose2':'nose_' + str(face2[2]) + '.jpg',
            'mouth2':'mouth_' + str(face2[3]) + '.jpg',
            'face1':",".join(map(str,face1)),
            'face2':",".join(map(str,face2)),
        }
        path = os.path.join(os.path.dirname(__file__), 'html/abface.html')
        self.response.out.write(template.render(path, template_values))

    def makeface(self):
        face = memcache.get("face")
        if face is None:
            face = [random.randint(1,5) for i in range(4)]
            memcache.set("face", face, 3600)
        return face

app = webapp2.WSGIApplication([
    ('/abface.html', Abface)
], debug=True)

首先,当用户访问时调用的是get()方法。
get()方法会调用draw()方法。结束。

所以,draw()方法的内容。这里是生成页面。
首先在第一行调用makeface()函数。一直被耍来耍去的感觉。

生成表情()。这里的关键是memcache。
时间一过,就会消失的缓存。
“face”关键字当前应该是一个包含最优表情[1,3,4,5]的数组(应该是)。
这个数组表示眉毛为1号,眼睛为3号,鼻子为4号,嘴巴为5号。
数据可能存储了类似的内容…但也可能没有存储。不能保证。
因为memcache是缓存,所以它可能已经消失了。
所以,如果face为空,就随机生成一个表情并保存。寿命为3600秒=1小时。
如果想永久保存,就必须保存在真正的数据库中,但由于这只是个娱乐项目,消失了也没关系。

因此返回draw()。
根据makeface()创建的脸部特征,对眉毛、眼睛、鼻子或嘴巴中的其中一个进行修改。这是另一种选择。
这里又出现了memcache。如果上次选择的脸部是B,那么将脸1和脸2互换。
然后将值设置到模板中,并传递给客户端。
这就是服务器端的脸部显示机制。

最后对post()进行解释。接收来自客户端的AB选择和选择的面部组合,并将其设置到memcache中。

接下来是客户端。

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
        <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
        <title>ABface</title>
        <style>
#canv1,#canv2 {
    border: solid 3px #000;
    border-radius: 25px 25px 25px 25px / 25px 25px 25px 25px;
    border-color: #ff0000;
}
#canv2 {
    border: solid 3px #000;
    border-radius: 25px 25px 25px 25px / 25px 25px 25px 25px;
    border-color: #0000ff;
}
#canv1:hover {
    box-shadow: 0px 0px 20px 5px #ff0000
}
#canv2:hover {
    box-shadow: 0px 0px 20px 5px #0000ff
}
#main {  
    width: 100%;
    text-align : center 
}
.hid{
    display:none;
}
        </style>
    </head>
    <body>
<div id="main">
<h1><span style="color:#ff0000">A</span> or <span style="color:#0000ff">B</span></h1>
<canvas id="canv1"  width="150" height="150"></canvas>
  <canvas id="canv2"  width="150" height="150"></canvas>
</div>
<form action="/abface.html" method="post" id ="frm">
    <input type="text" name="choice" id="choice" value="" style="display:none">
    <input type="text" name="sel" id="sel" value="" style="display:none">
</form>
<img src="img/face/{{ brow1 }}" id ="brow_1" class="hid">
<img src="img/face/{{ eye1 }}" id ="eye_1" class="hid">
<img src="img/face/{{ nose1 }}" id ="nose_1" class="hid">
<img src="img/face/{{ mouth1 }}" id ="mouse_1" class="hid">
<img src="img/face/{{ brow2 }}" id ="brow_2" class="hid">
<img src="img/face/{{ eye2 }}" id ="eye_2" class="hid">
<img src="img/face/{{ nose2 }}" id ="nose_2" class="hid">
<img src="img/face/{{ mouth2 }}" id ="mouse_2" class="hid">
<script>
var ctx1 = document.getElementById('canv1').getContext('2d');
var ctx2 = document.getElementById('canv2').getContext('2d');
var face1 = "{{ face1 }}"
var face2 = "{{ face2 }}"
function makeface(){
    ctx1.drawImage(document.getElementById('brow_1'), 0, 0)
    ctx1.drawImage(document.getElementById('eye_1'), 0, 25)
    ctx1.drawImage(document.getElementById('nose_1'), 0, 50)
    ctx1.drawImage(document.getElementById('mouse_1'), 0, 110)
    ctx2.drawImage(document.getElementById('brow_2'), 0, 0)
    ctx2.drawImage(document.getElementById('eye_2'), 0, 25)
    ctx2.drawImage(document.getElementById('nose_2'), 0, 50)
    ctx2.drawImage(document.getElementById('mouse_2'), 0, 110)
}
window.onload = function(){
    makeface()
        $("#canv1").bind("click",function(){
            ctx1.beginPath();
            ctx1.lineWidth = 10;
            ctx1.strokeStyle="#ff0000"; 
            ctx1.arc(75, 75, 50, 0, Math.PI*2, false)
            ctx1.stroke();
            $("#choice").val(face1);
            $("#sel").val("A");
            $('#frm').submit();
    });
        $("#canv2").bind("click",function(){
            ctx2.beginPath();
            ctx2.strokeStyle="#0000ff"; 
            ctx2.lineWidth = 10;  
            ctx2.arc(75, 75, 50, 0, Math.PI*2, false)
            ctx2.stroke();
            $("#choice").val(face2);
            $("#sel").val("B");
            $('#frm').submit();
    });
}
</script>
    </body>
</html>

首先要看的是makeface()函数。
将图片粘贴在画布上。
将图片粘贴在两个画布上。
IMG元素根据从服务器端接收到的部件编号切换URL。
显示的部分如下。

下面是当点击画布时的事件。
虽然有各种各样的处理,但因为是外观问题,所以可以基本忽略。
最重要的是最后三行。
设置所选组件、设置A或B,然后点击提交。
然后服务器端会调用post()函数。

以上就可以创建类似AB测试的东西了。

总结

如果能够增加零件的种类并选择轮廓、发型和布局等,梦想可能会变得更加广阔。

所有的素材都是用女性的脸来制作的,但最后得到的却是一张张男性的脸。
或许是因为部分的布局平衡问题吧。

广告
将在 10 秒后关闭
bannerAds