1#!/usr/bin/env python 2 3from itertools import product 4from functools import reduce 5 6import numpy as np 7import cv2 as cv 8 9from tests_common import NewOpenCVTests 10 11 12def norm_inf(x, y=None): 13 def norm(vec): 14 return np.linalg.norm(vec.flatten(), np.inf) 15 16 x = x.astype(np.float64) 17 return norm(x) if y is None else norm(x - y.astype(np.float64)) 18 19 20def norm_l1(x, y=None): 21 def norm(vec): 22 return np.linalg.norm(vec.flatten(), 1) 23 24 x = x.astype(np.float64) 25 return norm(x) if y is None else norm(x - y.astype(np.float64)) 26 27 28def norm_l2(x, y=None): 29 def norm(vec): 30 return np.linalg.norm(vec.flatten()) 31 32 x = x.astype(np.float64) 33 return norm(x) if y is None else norm(x - y.astype(np.float64)) 34 35 36def norm_l2sqr(x, y=None): 37 def norm(vec): 38 return np.square(vec).sum() 39 40 x = x.astype(np.float64) 41 return norm(x) if y is None else norm(x - y.astype(np.float64)) 42 43 44def norm_hamming(x, y=None): 45 def norm(vec): 46 return sum(bin(i).count('1') for i in vec.flatten()) 47 48 return norm(x) if y is None else norm(np.bitwise_xor(x, y)) 49 50 51def norm_hamming2(x, y=None): 52 def norm(vec): 53 def element_norm(element): 54 binary_str = bin(element).split('b')[-1] 55 if len(binary_str) % 2 == 1: 56 binary_str = '0' + binary_str 57 gen = filter(lambda p: p != '00', 58 (binary_str[i:i+2] 59 for i in range(0, len(binary_str), 2))) 60 return sum(1 for _ in gen) 61 62 return sum(element_norm(element) for element in vec.flatten()) 63 64 return norm(x) if y is None else norm(np.bitwise_xor(x, y)) 65 66 67norm_type_under_test = { 68 cv.NORM_INF: norm_inf, 69 cv.NORM_L1: norm_l1, 70 cv.NORM_L2: norm_l2, 71 cv.NORM_L2SQR: norm_l2sqr, 72 cv.NORM_HAMMING: norm_hamming, 73 cv.NORM_HAMMING2: norm_hamming2 74} 75 76norm_name = { 77 cv.NORM_INF: 'inf', 78 cv.NORM_L1: 'L1', 79 cv.NORM_L2: 'L2', 80 cv.NORM_L2SQR: 'L2SQR', 81 cv.NORM_HAMMING: 'Hamming', 82 cv.NORM_HAMMING2: 'Hamming2' 83} 84 85 86def get_element_types(norm_type): 87 if norm_type in (cv.NORM_HAMMING, cv.NORM_HAMMING2): 88 return (np.uint8,) 89 else: 90 return (np.uint8, np.int8, np.uint16, np.int16, np.int32, np.float32, 91 np.float64) 92 93 94def generate_vector(shape, dtype): 95 if np.issubdtype(dtype, np.integer): 96 return np.random.randint(0, 100, shape).astype(dtype) 97 else: 98 return np.random.normal(10., 12.5, shape).astype(dtype) 99 100 101shapes = (1, 2, 3, 5, 7, 16, (1, 1), (2, 2), (3, 5), (1, 7)) 102 103 104class norm_test(NewOpenCVTests): 105 106 def test_norm_for_one_array(self): 107 np.random.seed(123) 108 for norm_type, norm in norm_type_under_test.items(): 109 element_types = get_element_types(norm_type) 110 for shape, element_type in product(shapes, element_types): 111 array = generate_vector(shape, element_type) 112 expected = norm(array) 113 actual = cv.norm(array, norm_type) 114 self.assertAlmostEqual( 115 expected, actual, places=2, 116 msg='Array {0} of {1} and norm {2}'.format( 117 array, element_type.__name__, norm_name[norm_type] 118 ) 119 ) 120 121 def test_norm_for_two_arrays(self): 122 np.random.seed(456) 123 for norm_type, norm in norm_type_under_test.items(): 124 element_types = get_element_types(norm_type) 125 for shape, element_type in product(shapes, element_types): 126 first = generate_vector(shape, element_type) 127 second = generate_vector(shape, element_type) 128 expected = norm(first, second) 129 actual = cv.norm(first, second, norm_type) 130 self.assertAlmostEqual( 131 expected, actual, places=2, 132 msg='Arrays {0} {1} of type {2} and norm {3}'.format( 133 first, second, element_type.__name__, 134 norm_name[norm_type] 135 ) 136 ) 137 138 def test_norm_fails_for_wrong_type(self): 139 for norm_type in (cv.NORM_HAMMING, cv.NORM_HAMMING2): 140 with self.assertRaises(Exception, 141 msg='Type is not checked {0}'.format( 142 norm_name[norm_type] 143 )): 144 cv.norm(np.array([1, 2], dtype=np.int32), norm_type) 145 146 def test_norm_fails_for_array_and_scalar(self): 147 for norm_type in norm_type_under_test: 148 with self.assertRaises(Exception, 149 msg='Exception is not thrown for {0}'.format( 150 norm_name[norm_type] 151 )): 152 cv.norm(np.array([1, 2], dtype=np.uint8), 123, norm_type) 153 154 def test_norm_fails_for_scalar_and_array(self): 155 for norm_type in norm_type_under_test: 156 with self.assertRaises(Exception, 157 msg='Exception is not thrown for {0}'.format( 158 norm_name[norm_type] 159 )): 160 cv.norm(4, np.array([1, 2], dtype=np.uint8), norm_type) 161 162 def test_norm_fails_for_array_and_norm_type_as_scalar(self): 163 for norm_type in norm_type_under_test: 164 with self.assertRaises(Exception, 165 msg='Exception is not thrown for {0}'.format( 166 norm_name[norm_type] 167 )): 168 cv.norm(np.array([3, 4, 5], dtype=np.uint8), 169 norm_type, normType=norm_type) 170 171 172if __name__ == '__main__': 173 NewOpenCVTests.bootstrap() 174