libvips/test/test_convolution.py

104 lines
3.5 KiB
Python
Raw Normal View History

2014-12-15 17:14:02 +01:00
#!/usr/bin/python3
from __future__ import division
from builtins import zip
from builtins import range
from numbers import Number
import unittest
import math
#import logging
#logging.basicConfig(level = logging.DEBUG)
from gi.repository import Vips
2014-12-15 17:14:02 +01:00
# an expanding zip ... if either of the args is a scalar or a one-element list,
# duplicate it down the other side
def zip_expand(x, y):
# handle singleton list case
if isinstance(x, list) and len(x) == 1:
x = x[0]
if isinstance(y, list) and len(y) == 1:
y = y[0]
if isinstance(x, list) and isinstance(y, list):
return list(zip(x, y))
elif isinstance(x, list):
return [[i, y] for i in x]
elif isinstance(y, list):
return [[x, j] for j in y]
else:
return [[x, y]]
# run a 1-ary function on a thing -- loop over elements if the
# thing is a list
def run_fn(fn, x):
if isinstance(x, list):
return [fn(i) for i in x]
else:
return fn(x)
# run a 2-ary function on two things -- loop over elements pairwise if the
# things are lists
def run_fn2(fn, x, y):
if isinstance(x, Vips.Image) or isinstance(y, Vips.Image):
return fn(x, y)
elif isinstance(x, list) or isinstance(y, list):
return [fn(i, j) for i, j in zip_expand(x, y)]
else:
return fn(x, y)
# point convolution
def conv(image, mask, x_position, y_position):
s = 0.0
for x in range(0, mask.width):
for y in range(0, mask.height):
m = mask.getpoint(x, y)
i = image.getpoint(x + x_position, y + y_position)
p = run_fn2(lambda a, b: a * b, m, i)
s = run_fn2(lambda a, b: a + b, s, p)
return run_fn2(lambda a, b: a / b, s, mask.get_scale())
class TestConvolution(unittest.TestCase):
# test a pair of things which can be lists for approx. equality
def assertAlmostEqualObjects(self, a, b, places = 4, msg = ''):
#print 'assertAlmostEqualObjects %s = %s' % (a, b)
for x, y in zip_expand(a, b):
self.assertAlmostEqual(x, y, places = places, msg = msg)
def setUp(self):
im = Vips.Image.mask_ideal(100, 100, 0.5, reject = True, optical = True)
self.colour = im * [1, 2, 3] + [2, 3, 4]
self.mono = self.colour.extract_band(1)
self.all_images = [self.mono, self.colour]
sharp = Vips.Image.new_from_array([[-1, -1, -1],
[-1, 16, -1],
[-1, -1, -1]], scale = 8)
blur = Vips.Image.new_from_array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]], scale = 9)
line = Vips.Image.new_from_array([[1, 1, 1], [-2, -2, -2], [1, 1, 1]])
sobel = Vips.Image.new_from_array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]])
self.all_masks = [sharp, blur, line, sobel]
def test_conv(self):
for im in self.all_images:
for msk in self.all_masks:
for prec in [Vips.Precision.INTEGER, Vips.Precision.FLOAT]:
convolved = im.conv(msk, precision = prec)
result = convolved.getpoint(25, 50)
true = conv(im, msk, 24, 49)
self.assertAlmostEqualObjects(result, true)
result = convolved.getpoint(50, 50)
true = conv(im, msk, 49, 49)
self.assertAlmostEqualObjects(result, true)
2014-12-15 17:14:02 +01:00
if __name__ == '__main__':
unittest.main()