Skip to content
This repository has been archived by the owner on Oct 31, 2023. It is now read-only.

Use different Docker image for blender verification #3844

Merged
merged 8 commits into from
Feb 19, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
400 changes: 0 additions & 400 deletions apps/blender/blender_reference_generator.py

This file was deleted.

36 changes: 36 additions & 0 deletions apps/blender/resources/images/blender_verifier.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
FROM golemfactory/blender:1.8

# Install scripts requirements first, then add scripts.
ADD scripts_verifier/requirements.txt /golem/work/
ADD scripts_verifier/copy.sh /golem/

# Install any needed packages specified in requirements.txt
RUN set +x \
&& apt-get update \
&& apt-get install -y libglib2.0-0 \
&& apt-get install -y g++ \
&& apt-get install -y libsm6 \
&& apt-get install -y libxrender1 \
&& apt-get install -y wget \
&& apt-get install -y zlib1g-dev \
&& apt-get install -y libopenexr-dev \
&& /golem/install_py_libs.sh /golem/work/requirements.txt \
&& /golem/copy.sh \
&& apt-get remove -y libopenexr-dev \
&& apt-get remove -y zlib1g-dev \
&& apt-get remove -y wget \
&& apt-get remove -y libxrender1 \
&& apt-get remove -y libsm6 \
&& apt-get remove -y g++ \
&& apt-get remove -y libglib2.0-0 \
&& apt-get clean \
&& apt-get -y autoremove \
&& rm -rf /var/lib/apt/lists/*

ENV PYTHONPATH=/golem/scripts:/golem/scripts_verifier:/golem:$PYTHONPATH

# Create symbolic link to python. I don't know where, something removes it.
RUN ln -s /usr/bin/python3.6 /usr/bin/python3

RUN mkdir /golem/scripts_verifier
ADD scripts_verifier/ /golem/scripts_verifier
9 changes: 9 additions & 0 deletions apps/blender/resources/images/scripts_verifier/copy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cp /usr/lib/x86_64-linux-gnu/libXrender.so.1 /usr/local/lib/.
cp /usr/lib/x86_64-linux-gnu/libSM.so.6 /usr/local/lib/.
cp /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0 /usr/local/lib/.
cp /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0 /usr/local/lib/.
cp /usr/lib/x86_64-linux-gnu/libICE.so.6 /usr/local/lib/.
cp /usr/lib/x86_64-linux-gnu/libIex-2_2.so.12 /usr/local/lib/.
cp /usr/lib/x86_64-linux-gnu/libIlmImf-2_2.so.22 /usr/local/lib/.
cp /usr/lib/x86_64-linux-gnu/libHalf.so.12 /usr/local/lib/.
cp /usr/lib/x86_64-linux-gnu/libIlmThread-2_2.so.12 /usr/local/lib/.
173 changes: 173 additions & 0 deletions apps/blender/resources/images/scripts_verifier/crop_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import os
import numpy
import math
import random
from typing import Dict, Tuple, List, Optional

WORK_DIR = "/golem/work"
OUTPUT_DIR = "/golem/output"

class Region:

def __init__(self, left: float, top: float, right: float, bottom: float):
self.left = left
self.right = right
self.top = top
self.bottom = bottom

class PixelRegion:

def __init__(self, left: int, top: int, right: int, bottom: int):
self.left = left
self.right = right
self.top = top
self.bottom = bottom

class SubImage:

CROP_RELATIVE_SIZE = 0.1
PIXEL_OFFSET = numpy.float32(0.5)
MIN_CROP_SIZE = 8

def __init__(self, region: Region, resolution: List[int]):
self.region = region
self.pixel_region = self.calculate_pixels(region, resolution[0], resolution[1])
self.width = self.pixel_region.right - self.pixel_region.left
self.height = self.pixel_region.top - self.pixel_region.bottom
self.resolution = resolution

def calculate_pixels(self, region: Region, width: int, height: int) -> None:
# This is how Blender is calculating pixel, check
# BlenderSync::get_buffer_params in blender_camera.cpp file
# BoundBox2D border = cam->border.clamp();
# params.full_x = (int)(border.left * (float)width);

# NOTE blender uses floats (single precision) while python operates on
# doubles
# Here numpy is used to emulate this loss of precision when assigning
# double to float:
left = math.floor(
numpy.float32(region.left) * numpy.float32(width) +
SubImage.PIXEL_OFFSET)

right = math.floor(
numpy.float32(region.right) * numpy.float32(width) +
SubImage.PIXEL_OFFSET)

# NOTE we are exchanging here top with bottom, because borders
# in blender are in OpenGL UV coordinate system (left, bottom is 0,0)
# where pixel values are for use in classic coordinate system (left, top is 0,0)

top = math.floor(
numpy.float32(region.bottom) * numpy.float32(height) +
SubImage.PIXEL_OFFSET)

bottom = math.floor(
numpy.float32(region.top) * numpy.float32(height) +
SubImage.PIXEL_OFFSET)

print("Pixels left=%r, top=%r, right=%r, bottom=%r" %
(left, top, right, bottom))
return PixelRegion(left, top, right, bottom)

@staticmethod
def __calculate_crop_side_length(subtask_side_length: int) -> int:
calculated_length = int(
SubImage.CROP_RELATIVE_SIZE * subtask_side_length)

return max(SubImage.MIN_CROP_SIZE, calculated_length)

def get_default_crop_size(self) -> Tuple[int, int]:
x = self.__calculate_crop_side_length(self.width)
y = self.__calculate_crop_side_length(self.height)
return x, y

class Crop:

@staticmethod
def create_from_region(id: int, crop_region: Region, subimage: SubImage):
crop = Crop(id, subimage)
crop.crop_region = crop_region
crop.pixel_region = crop.subimage.calculate_pixels(crop_region,
subimage.width, subimage.height)
return crop

@staticmethod
def create_from_pixel_region(id: int, pixel_region: PixelRegion, subimage: SubImage):
crop = Crop(id, subimage)
crop.pixel_region = pixel_region
crop.crop_region = crop.calculate_borders(pixel_region, subimage.resolution[0], subimage.resolution[1])
return crop

def __init__(self, id: int, subimage: SubImage):
self.id = id
self.subimage = subimage
self.pixel_region = None
self.crop_region = None

def get_relative_top_left(self) \
-> Tuple[int, int]:
# get top left corner of crop in relation to particular subimage
print("Sumimag top=%r - crop.top=%r" % (self.subimage.region.top, self.pixel_region.top))
y = self.subimage.pixel_region.top - self.pixel_region.top
print("X=%r, Y=%r" % (self.pixel_region.left, y))
return self.pixel_region.left, y

def calculate_borders(self, pixel_region: PixelRegion, width: int, height: int):

left = numpy.float32(
(numpy.float32(pixel_region.left) + SubImage.PIXEL_OFFSET) /
numpy.float32(width))

right = numpy.float32(
(numpy.float32(pixel_region.right) + SubImage.PIXEL_OFFSET) /
numpy.float32(width))

bottom = numpy.float32(
(numpy.float32(pixel_region.top) + SubImage.PIXEL_OFFSET) /
numpy.float32(height))

top = numpy.float32(
(numpy.float32(pixel_region.bottom) + SubImage.PIXEL_OFFSET) /
numpy.float32(height))

return Region(left, top, right, bottom)

def generate_single_random_crop_data(subimage: SubImage, crop_size_px: Tuple[int, int], id: int) \
-> Crop:

crop_horizontal_pixel_coordinates = _get_random_interval_within_boundaries(
subimage.pixel_region.left,
subimage.pixel_region.right,
crop_size_px[0])

crop_vertical_pixel_coordinates = _get_random_interval_within_boundaries(
subimage.pixel_region.bottom,
subimage.pixel_region.top,
crop_size_px[1])

crop = Crop.create_from_pixel_region(id, PixelRegion(
crop_horizontal_pixel_coordinates[0],
crop_vertical_pixel_coordinates[1],
crop_horizontal_pixel_coordinates[1],
crop_vertical_pixel_coordinates[0]), subimage)

return crop

def _get_random_interval_within_boundaries(begin: int,
end: int,
interval_length: int) \
-> Tuple[int, int]:

# survive in edge cases
end -= 1
begin += 1

print("begin %r, end %r" % (begin, end))

max_possible_interval_end = (end - interval_length)
if max_possible_interval_end < 0:
raise Exception("Subtask is too small for reliable verification")
interval_begin = random.randint(begin, max_possible_interval_end)
interval_end = interval_begin + interval_length
return interval_begin, interval_end
40 changes: 40 additions & 0 deletions apps/blender/resources/images/scripts_verifier/decision_tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import numpy
from sklearn.externals import joblib


## ======================= ##
##
class DecisionTree:

## ======================= ##
##
def __init__( self, clf ):
self.clf = clf

## ======================= ##
##
@staticmethod
def load( file ):
data = joblib.load( file )
tree = DecisionTree( data[0] )

return tree, data[1]

## ======================= ##
##
def classify_with_feature_vector(self, feature_vector, labels):

numpy_format = []
for label in labels:
numpy_format.append((label, numpy.float64))

converted_features = numpy.zeros(1, dtype=numpy_format)
for name in converted_features.dtype.names:
converted_features[name] = feature_vector[name]

samples = converted_features.view(numpy.float64).reshape(
converted_features.shape + (-1,))

results = self.clf.predict(samples)

return numpy.array(results)
63 changes: 63 additions & 0 deletions apps/blender/resources/images/scripts_verifier/edges.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from PIL import Image, ImageFilter
import numpy
from skimage import compare_mse


import sys


## ======================= ##
##
class MetricEdgeFactor:


## ======================= ##
##
@staticmethod
def compute_metrics( image1, image2 ):

image1 = image1.convert("RGB")
image2 = image2.convert("RGB")

edged_image1 = image1.filter( ImageFilter.FIND_EDGES )
edged_image2 = image2.filter( ImageFilter.FIND_EDGES )

np_image1 = numpy.array( edged_image1 )
np_image2 = numpy.array( edged_image2 )

ref_edge_factor = numpy.mean( np_image1 )
comp_edge_factor = numpy.mean( np_image2 )

edge_factor = compare_mse( np_image1, np_image2 )

result = dict()
result[ "ref_edge_factor" ] = ref_edge_factor
result[ "comp_edge_factor" ] = comp_edge_factor
result[ "edge_difference" ] = edge_factor

return result

## ======================= ##
##
@staticmethod
def get_labels():
return [ "ref_edge_factor", "comp_edge_factor", "edge_difference" ]

## ======================= ##
##
def run():

first_img = sys.argv[ 1 ]
second_img = sys.argv[ 2 ]

first_img = Image.open( first_img )
second_img = Image.open( second_img )

ssim = MetricEdgeFactor()

print( ssim.compute_metrics( first_img, second_img ) )



if __name__ == "__main__":
run()
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import cv2
import numpy
from PIL import Image
import sys


class MetricHistogramsCorrelation:

@staticmethod
def compute_metrics( image1, image2):
if image1.size != image2.size:
raise Exception("Image sizes differ")
opencv_image_1 = cv2.cvtColor(numpy.array(image1), cv2.COLOR_RGB2BGR)
opencv_image_2 = cv2.cvtColor(numpy.array(image2), cv2.COLOR_RGB2BGR)
return {"histograms_correlation": MetricHistogramsCorrelation.compare_histograms(opencv_image_1, opencv_image_2)}

@staticmethod
def get_labels():
return ["histograms_correlation"]

@staticmethod
def get_number_of_pixels(image):
height, width = image.shape[:2]
return height * width

@staticmethod
def calculate_normalized_histogram(image):
number_of_bins = 256
channels_number = 3 # because of conversion from PIL to opencv
histogram = cv2.calcHist([image],
range(channels_number),
None,
[number_of_bins] * channels_number,
[0, 256] * channels_number)
cv2.normalize(histogram, histogram, 0, 256, cv2.NORM_MINMAX)
return histogram

@staticmethod
def compare_histograms(image_a, image_b):
histogram_a = MetricHistogramsCorrelation.calculate_normalized_histogram(image_a)
histogram_b = MetricHistogramsCorrelation.calculate_normalized_histogram(image_b)
result = cv2.compareHist(histogram_a, histogram_b, cv2.HISTCMP_CORREL)
return result


def run():
first_img = Image.open(sys.argv[1])
second_img = Image.open(sys.argv[2])

histograms_correlation_metric = MetricHistogramsCorrelation()

print(histograms_correlation_metric.compute_metrics(first_img, second_img))


if __name__ == "__main__":
run()
Loading