Browse Source

Merge branch 'release/v0.2.6'

Jérôme BUISINE 4 months ago
parent
commit
4017241c73

+ 44 - 10
expe/config.py

@@ -30,30 +30,64 @@ expes_configuration            = {
 
     # First experiments configuration
     'quest_one_image':{
+        'scenes':['contemporary', 'bathroom'],
         'text':{
             'question': "Do you see one image or a composition of more than one?",
-            'indication': "press left if you see one image, right if not",
+            'indication': "press RIGHT if you see 2 images, LEFT if not",
             'end_text': "Experience is finished. Thanks for your participation",
             'examples': {
-                'sentence': "This images is cropped {0} with {1}%",
+                'sentence': ["1st example : ", 
+                             "The answer is 2 images! \n This image is cropped {0}.\n {1}% on the left originating from a low-quality image and on the right originating from high quality. \n So, press RIGHT.",
+                             "2nd example : ",
+                             "The answer is 1 image! \n This image is cropped {0} but \n {1}% on the left originating from a high-quality image and on the right originating from high quality, too.\n So, press LEFT.", 
+                             "3rd example: ",
+                             "The answer is 2 images! \n This image is cropped {0}. \n {1}% on the upper part originating from a low-quality image and on the bottom originating from high quality. \n So, press RIGHT.",
+                             "4th example: ",
+                             "The answer is 2 images! \n This image is cropped {0}. \n {1}% on the upper part originating from a low-quality image and on the bottom originating from high quality. \n So, press RIGHT.",
+                             "5th example: ",
+                             "The answer is 1 image! \n This image is cropped {0}. \n {1}% on the upper part originating from a high-quality image and on the bottom originating from a low-quality quality.\n So, press RIGHT.",
+                             "6th example: ",
+                             "The answer is 2 images! \n This image is cropped {0}. \n {1}% on the left originating from a low-quality image and on the right originating from high quality. \n So, press RIGHT.",
+                             ],
                 'crop_params': [
                     [0.3, 0, 0],
                     [0.3, 0, 0],
-                    [0.7, 1, 0]
+                    [0.3, 0, 0],
+                    [0.3, 0, 0],
+                    [0.7, 1, 0],
+                    [0.7, 1, 0],
+                    [0.2, 1, 0],
+                    [0.2, 1, 0],
+                    [0.8, 1, 1],
+                    [0.8, 1, 1],
+                    [0.2, 0, 0],
+                    [0.2, 0, 0]
                 ],
                 'images': [
-                    [2, -1],
-                    [-3, -1],
-                    [7, -1]
+                    [1, -1],
+                    [1, -1],
+                    [-1, -1],
+                    [-1, -1],
+                    [7, -1],
+                    [7, -1],
+                    [15, -1],
+                    [15, -1],
+                    [20, -1],
+                    [20, -1],
+                    [30, -1],
+                    [30, -1]
                 ]
             }
         },
         'params':{
-            'iterations': 10
-        },
-        'slopes':{
-
+            'iterations': 100,
+            'entropy': 5,
+            'slopes':{
+                'contemporary' : [0.0001, 0.001, 0.00003], #start, stop, step
+                'bathroom' : [0.0005, 0.01, 0.0003], #start, stop, step
+            },
         },
+        
         # if others custom session param are directly set for experiments
         'session_params': [
             'expe_data',

+ 75 - 2
expe/expes/run.py

@@ -22,6 +22,69 @@ from .classes.quest_plus import psychometric_fun
 from ipfml import utils
 from pprint import pprint
 
+from PIL import Image, ImageDraw
+
+def example_quest_one_image(request, expe_name, scene_name):
+    
+    example_number = request.GET.get('example')
+
+    
+    # get expected image qualities indices (load noisy and ref image)
+    params_image = cfg.expes_configuration[expe_name]['text']['examples']['images'][int(example_number)]
+    qualities = api.get_scene_qualities(scene_name)
+
+    noisy_quality = qualities[params_image[0]]
+    ref_quality = qualities[params_image[1]]
+
+    noisy_image = api.get_image(scene_name, noisy_quality)
+    ref_image = api.get_image(scene_name, ref_quality)
+
+    # get crop params from configuration
+    crop_params = cfg.expes_configuration[expe_name]['text']['examples']['crop_params'][int(example_number)]
+
+    img_merge, percentage, orientation, position = crop_images(noisy_image,     
+                                                                ref_image, 
+                                                                per=crop_params[0], 
+                                                                orien=crop_params[1], 
+                                                                swap_img=crop_params[2])
+    width, height = img_merge.size
+    if orientation==0:
+        left, top, right, bottom = percentage*width, 0, percentage*width, height   #vertical
+    else:
+        left, top, right, bottom = 0, percentage*height, width, percentage*height   #horizontal
+    if  int(example_number) % 2 != 0 :
+        if noisy_quality != qualities[-1]:#-noisy_quality > qualities[-1]-(10*qualities[-1])/100 :
+            draw = ImageDraw.Draw(img_merge) 
+            draw.line((left, top, right, bottom), fill='black', width=5)
+    example_sentence = cfg.expes_configuration[expe_name]['text']['examples']['sentence'][int(example_number)]
+
+    if orientation == 0:
+        example_sentence = example_sentence.format('vertically', str(percentage*100))
+    else:
+        example_sentence = example_sentence.format('horizontally', str(percentage*100))
+    
+    
+    # Temporary save of image
+    tmp_folder = os.path.join(settings.MEDIA_ROOT, cfg.output_tmp_folder)
+
+    if not os.path.exists(tmp_folder):
+        os.makedirs(tmp_folder)
+
+    # generate tmp merged image (pass as BytesIO was complicated..)
+    filepath_img = os.path.join(tmp_folder, 'example_' + scene_name + '' + expe_name + '.png')
+    
+    # replace img_merge if necessary (new iteration of expe)
+    if img_merge is not None:
+        img_merge.save(filepath_img)
+
+    data_example = {
+        'example_sentence': example_sentence,
+        'example': filepath_img
+    }
+
+    return data_example
+
+    
 
 def run_quest_one_image(request, model_filepath, output_file):
 
@@ -63,9 +126,13 @@ def run_quest_one_image(request, model_filepath, output_file):
     # TODO : add specific thresholds information for scene
     #thresholds = np.arange(50, 10000, 50)
     stim_space = np.asarray(qualities)
+    
+    slope_range = cfg.expes_configuration[expe_name]['params']['slopes'][scene_name]
+    slopes = np.arange(slope_range[0], slope_range[1], slope_range[2]) 
     #slopes = np.arange(0.0001, 0.001, 0.00003) # contemporary
-    slopes = np.arange(0.0005, 0.01, 0.0003) # bathroom
-
+    #slopes = np.arange(0.0005, 0.01, 0.0003) # bathroom
+    #slopes = np.arange(1.995,19.95,0.5985)
+    
     # TODO : update norm slopes
     # stim_space = np.asarray(qualities)
     # slopes = np.arange(0.0001, 0.001, 0.00003)
@@ -113,6 +180,10 @@ def run_quest_one_image(request, model_filepath, output_file):
 
         output_file.write(line)
         output_file.flush()
+        
+        if entropy < cfg.expes_configuration[expe_name]['params']['entropy']:
+            request.session['expe_finished'] = True
+            return None
 
     # 5. Contruct new image and save it
     # construct image 
@@ -139,6 +210,8 @@ def run_quest_one_image(request, model_filepath, output_file):
     else:
         request.session['expe_finished'] = True
         return None
+    
+    
 
     # save image using user information
     # create output folder for tmp files if necessary

+ 2 - 2
expe/templates/expe/expe_indications.html

@@ -33,9 +33,9 @@
 
         <p id="expeIndication"><strong>Press enter to begin experiments</strong></p>
     {% else %}
+        <input type="hidden" name="scene_name" value="{{scene_name}}"/>
         <br/>
-        <h5>{{example_sentence}}</h5>
-        <br/>
+        <h5>{{example_sentence|linebreaks}}</h5>
         <img src="{{example}}" />
     {% endif %}
 

+ 10 - 9
expe/templates/expe/expe_list.html

@@ -16,15 +16,6 @@
 
                 <input type="hidden" name="example" value="0"/>
 
-                <div class="form-group">
-                    <label for="scene">Select scene:</label>
-                    <select class="form-control" name="scene">
-                        {% for scene in scenes %}
-                            <option value="{{scene}}">{{scene}}</option>
-                        {% endfor %}
-                    </select>
-                </div>
-
                 <div class="form-group">
                     <label for="expe" style="position:static">Select experiments:</label>
                     <select class="form-control " name="expe">
@@ -33,6 +24,16 @@
                         {% endfor %}
                     </select>
                 </div>
+                
+                <!-- <div class="form-group">
+                    <label for="scene">Select scene:</label>
+                    <select class="form-control" name="scene">
+                        {% for scene in scenes. %}
+                            <option value="{{scene}}">{{scene}}</option>
+                        {% endfor %}
+                    </select>
+                </div> -->
+
 
                 <button type="submit" class="btn btn-primary">Submit</button>
             </form>

+ 3 - 3
expe/templates/expe/expe_results.html

@@ -10,7 +10,7 @@
 {% block content %}
     
     {% if not expe %}
-        <h3>Results files of experimentss</h3>
+        <h3>Results files of experiments</h3>
         <br />
     {% endif %}
 
@@ -59,10 +59,10 @@
                                             <ul class="list-group files-list" style="display: none">
 
                                                 <hr />
-                                                <li class="list-group-item">
                                                 
                                                 {% for user_name, user in day.items %}
 
+                                                <li class="list-group-item">
 
                                                         <div class="row">
                                                             <div class="col-md-10"><strong>User: </strong>{{user_name}} </div>
@@ -118,10 +118,10 @@
                                     <ul class="list-group files-list" style="display: none">
 
                                         <hr />
-                                        <li class="list-group-item">
                                         
                                         {% for user_name, user in day.items %}
 
+                                        <li class="list-group-item">
 
                                                 <div class="row">
                                                     <div class="col-md-10"><strong>User: </strong>{{user_name}} </div>

+ 82 - 47
expe/views.py

@@ -26,7 +26,7 @@ from .expes import run as run_expe
 
 # image processing imports
 import io
-from PIL import Image
+from PIL import Image, ImageDraw
 
 # module imports
 from .utils import api
@@ -68,17 +68,33 @@ def expe_list(request):
     # expe data
     data['scenes'] = scenes
     data['expes']  = expes
-
+    
+    #data['scenes'] = {}
+    #for expe in expes:
+    #    if 'scene' in cfg.expes_configuration[expe]:
+    #        data['scenes'][expe] = cfg.expes_configuration[expe]['scenes']
+    #    else:
+    #        data['scenes'][expe] = scenes
+            
     return render(request, 'expe/expe_list.html', data)
 
 
 def indications(request):
 
-    random.seed(10)
+    #random.seed(10)
 
     # get param 
     expe_name = request.GET.get('expe')
-    scene_name = request.GET.get('scene')
+    
+
+    
+    scene_name = None
+    if 'scene' in request.GET:
+        scene_name = request.GET.get('scene')
+    
+    if scene_name is None or scene_name == 'null':
+        scene_name = random.choice(cfg.expes_configuration[expe_name]['scenes'])
+        
     example_number = request.GET.get('example')
 
     print(example_number)
@@ -97,50 +113,69 @@ def indications(request):
     if (int(example_number) >= number_of_examples):
         start_experiment = True
     else:
+         # run expe method using `expe_name`
+        function_name = 'example_' + expe_name
+    
+        try:
+            run_example_method = getattr(run_expe, function_name)
+        except AttributeError:
+            raise NotImplementedError("Run expe method `{}` not implement `{}`".format(run_expe.__name__, function_name))
+    
+        data_example = run_example_method(request, expe_name, scene_name)
+        data.update(data_example)
+         
         # get expected image qualities indices (load noisy and ref image)
-        params_image = cfg.expes_configuration[expe_name]['text']['examples']['images'][int(example_number)]
-        qualities = api.get_scene_qualities(scene_name)
-
-        noisy_quality = qualities[params_image[0]]
-        ref_quality = qualities[params_image[1]]
-
-        noisy_image = api.get_image(scene_name, noisy_quality)
-        ref_image = api.get_image(scene_name, ref_quality)
-
-        # get crop params from configuration
-        crop_params = cfg.expes_configuration[expe_name]['text']['examples']['crop_params'][int(example_number)]
-
-        img_merge, percentage, orientation, position = crop_images(noisy_image,     
-                                                                    ref_image, 
-                                                                    per=crop_params[0], 
-                                                                    orien=crop_params[1], 
-                                                                    swap_img=crop_params[2])
-
-        example_sentence = cfg.expes_configuration[expe_name]['text']['examples']['sentence']
-
-        if orientation == 0:
-            example_sentence = example_sentence.format('vertically', str(percentage*100))
-        else:
-            example_sentence = example_sentence.format('horizontally', str(percentage*100))
-
-        data['example_sentence'] = example_sentence
-
-
-        # Temporary save of image
-        tmp_folder = os.path.join(settings.MEDIA_ROOT, cfg.output_tmp_folder)
-
-        if not os.path.exists(tmp_folder):
-            os.makedirs(tmp_folder)
-
-        # generate tmp merged image (pass as BytesIO was complicated..)
-        filepath_img = os.path.join(tmp_folder, 'example_' + scene_name + '' + expe_name + '.png')
-        
-        # replace img_merge if necessary (new iteration of expe)
-        if img_merge is not None:
-            img_merge.save(filepath_img)
-
-        print(filepath_img)
-        data['example'] = filepath_img
+#        params_image = cfg.expes_configuration[expe_name]['text']['examples']['images'][int(example_number)]
+#        qualities = api.get_scene_qualities(scene_name)
+#
+#        noisy_quality = qualities[params_image[0]]
+#        ref_quality = qualities[params_image[1]]
+#
+#        noisy_image = api.get_image(scene_name, noisy_quality)
+#        ref_image = api.get_image(scene_name, ref_quality)
+#
+#        # get crop params from configuration
+#        crop_params = cfg.expes_configuration[expe_name]['text']['examples']['crop_params'][int(example_number)]
+#
+#        img_merge, percentage, orientation, position = crop_images(noisy_image,     
+#                                                                    ref_image, 
+#                                                                    per=crop_params[0], 
+#                                                                    orien=crop_params[1], 
+#                                                                    swap_img=crop_params[2])
+#        width, height = img_merge.size
+#        if orientation==0:
+#            left, top, right, bottom = percentage*width, 0, percentage*width, height   #vertical
+#        else:
+#            left, top, right, bottom = 0, percentage*height, width, percentage*height   #horizontal
+#        if  int(example_number) % 2 != 0 :
+#            if noisy_quality != qualities[-1]:#-noisy_quality > qualities[-1]-(10*qualities[-1])/100 :
+#                draw = ImageDraw.Draw(img_merge) 
+#                draw.line((left, top, right, bottom), fill='black', width=5)
+#        example_sentence = cfg.expes_configuration[expe_name]['text']['examples']['sentence'][int(example_number)]
+#
+#        if orientation == 0:
+#            example_sentence = example_sentence.format('vertically', str(percentage*100))
+#        else:
+#            example_sentence = example_sentence.format('horizontally', str(percentage*100))
+#
+#        data['example_sentence'] = example_sentence
+#
+#
+#        # Temporary save of image
+#        tmp_folder = os.path.join(settings.MEDIA_ROOT, cfg.output_tmp_folder)
+#
+#        if not os.path.exists(tmp_folder):
+#            os.makedirs(tmp_folder)
+#
+#        # generate tmp merged image (pass as BytesIO was complicated..)
+#        filepath_img = os.path.join(tmp_folder, 'example_' + scene_name + '' + expe_name + '.png')
+#        
+#        # replace img_merge if necessary (new iteration of expe)
+#        if img_merge is not None:
+#            img_merge.save(filepath_img)
+#
+#        print(filepath_img)
+#        data['example'] = filepath_img
 
     data['start'] = start_experiment
 

+ 7 - 3
static/js/indications.js

@@ -6,14 +6,18 @@ const KEYCODE_RIGHT_ARROW = 39
 
 urlParams = new URLSearchParams(window.location.search)
 
-const scene    = urlParams.get('scene')
+var scene      = urlParams.get('scene')
 const expe     = urlParams.get('expe')
 var example    = urlParams.get('example')
 
-if (example === null || example === ''){
+if (example == null || example == ''){
      example = 0
 }
 
+if (scene === null || scene === ''){
+     scene = document.getElementsByName('scene_name')[0].value
+}
+
 const checkKey = e => {
      if (e.keyCode === KEYCODE_Q) {
           // `q` to quit expe
@@ -28,11 +32,11 @@ const checkKey = e => {
           window.location = expeUrl + params
      }
      else if (e.keyCode === KEYCODE_LEFT_ARROW || e.keyCode === KEYCODE_RIGHT_ARROW) {
-          
           // increment number of example
           example = parseInt(example) + 1
 
           console.log("I'm here")
+          
           // construct url with params for experiments
           const params = `?scene=${scene}&expe=${expe}&example=${example}`
           window.location = indicationsUrl + params