| |
|
|
| |
| |
| from __future__ import division |
|
|
| import atexit |
| import logging |
| import os |
| import re |
| import subprocess |
| import sys |
| import threading |
|
|
| import psutil |
|
|
| |
| METEOR_JAR = 'meteor-1.5.jar' |
|
|
|
|
| def enc(s): |
| return s.encode('utf-8') |
|
|
|
|
| def dec(s): |
| return s.decode('utf-8') |
|
|
|
|
| class Meteor: |
|
|
| def __init__(self): |
| |
| self.lock = threading.Lock() |
|
|
| mem = '1G' |
| mem_available_G = psutil.virtual_memory().available / 1E9 |
| if mem_available_G < 2: |
| logging.warning("There is less than 2GB of available memory.\n" |
| "Will try with limiting Meteor to 1GB of memory but this might cause issues.\n" |
| "If you have problems using Meteor, " |
| "then you can try to lower the `mem` variable in meteor.py") |
| mem = '1G' |
|
|
| meteor_cmd = ['java', '-jar', '-Xmx{}'.format(mem), METEOR_JAR, |
| '-', '-', '-stdio', '-l', 'en', '-norm'] |
| env = os.environ.copy() |
| env['LC_ALL'] = "C" |
| self.meteor_p = subprocess.Popen(meteor_cmd, |
| cwd=os.path.dirname(os.path.abspath(__file__)), |
| env=env, |
| stdin=subprocess.PIPE, |
| stdout=subprocess.PIPE, |
| stderr=subprocess.PIPE) |
|
|
| atexit.register(self.close) |
|
|
| def close(self): |
| with self.lock: |
| if self.meteor_p: |
| self.meteor_p.kill() |
| self.meteor_p.wait() |
| self.meteor_p = None |
| |
| |
| if atexit is not None and atexit.unregister is not None: |
| atexit.unregister(self.close) |
|
|
| def compute_score(self, gts, res): |
| assert (gts.keys() == res.keys()) |
| imgIds = gts.keys() |
| scores = [] |
|
|
| eval_line = 'EVAL' |
| with self.lock: |
| for i in imgIds: |
| assert (len(res[i]) == 1) |
| stat = self._stat(res[i][0], gts[i]) |
| eval_line += ' ||| {}'.format(stat) |
|
|
| self.meteor_p.stdin.write(enc('{}\n'.format(eval_line))) |
| self.meteor_p.stdin.flush() |
| for i in range(0, len(imgIds)): |
| v = self.meteor_p.stdout.readline() |
| try: |
| scores.append(float(dec(v.strip()))) |
| except: |
| sys.stderr.write("Error handling value: {}\n".format(v)) |
| sys.stderr.write("Decoded value: {}\n".format(dec(v.strip()))) |
| sys.stderr.write("eval_line: {}\n".format(eval_line)) |
| |
| |
| |
| raise |
| score = float(dec(self.meteor_p.stdout.readline()).strip()) |
| self.close() |
| return score, scores |
|
|
| def method(self): |
| return "METEOR" |
|
|
| def _stat(self, hypothesis_str, reference_list): |
| |
| hypothesis_str = hypothesis_str.replace('|||', '') |
| score_line = ' ||| '.join(('SCORE', ' ||| '.join(reference_list), hypothesis_str)) |
| score_line = re.sub(r'\s+', ' ', score_line) |
| self.meteor_p.stdin.write(enc(score_line)) |
| self.meteor_p.stdin.write(enc('\n')) |
| self.meteor_p.stdin.flush() |
| return dec(self.meteor_p.stdout.readline()).strip() |
|
|
| def _score(self, hypothesis_str, reference_list): |
| with self.lock: |
| |
| hypothesis_str = hypothesis_str.replace('|||', '').replace(' ', ' ') |
| score_line = ' ||| '.join(('SCORE', ' ||| '.join(reference_list), hypothesis_str)) |
| self.meteor_p.stdin.write(enc('{}\n'.format(score_line))) |
| self.meteor_p.stdin.flush() |
| stats = dec(self.meteor_p.stdout.readline()).strip() |
| eval_line = 'EVAL ||| {}'.format(stats) |
| |
| self.meteor_p.stdin.write(enc('{}\n'.format(eval_line))) |
| self.meteor_p.stdin.flush() |
| score = float(dec(self.meteor_p.stdout.readline()).strip()) |
| |
| |
| score = float(dec(self.meteor_p.stdout.readline()).strip()) |
| return score |
|
|
| def __del__(self): |
| self.close() |
|
|