forked from tryone144/compton
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
compton-convgen: Misc: Clean up. The commit brings no change to the functionality of the script. - Partially fix PEP 8 compliance: - Place imports on separate lines. - Replace leading tabs with 4 spaces. - Add docstrings to classes and functions. - Surround top-level function and class definitions with two blank lines. - Remove spaces around keyword arguments. - Move all statements to separate lines. - Break some long lines into several lines. - Remove trailing semicolons after statements. - CGError: Use functionality from the base class Exception to store the description, instead of the custom logic. - CGInternal: Remove, as it is unused. - Hide the internal function gen_invalid() and args_readfactors() by prefixing their names with an underscore. - Move the module-level command-line handling code to two new functions, _main() and _parse_args(), and only execute if running in the main scope.
- Loading branch information
Showing
1 changed file
with
137 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,132 +1,161 @@ | ||
#! /usr/bin/env python3 | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
# vim:fileencoding=utf-8 | ||
|
||
import math, argparse | ||
import math | ||
import argparse | ||
|
||
|
||
class CGError(Exception): | ||
def __init__(self, value): | ||
self.value = value | ||
def __str__(self): | ||
return repr(self.value) | ||
'''An error in the convolution kernel generator.''' | ||
def __init__(self, desc): | ||
super().__init__(desc) | ||
|
||
|
||
class CGBadArg(CGError): | ||
'''An exception indicating an invalid argument has been passed to the | ||
convolution kernel generator.''' | ||
pass | ||
|
||
class CGBadArg(CGError): pass | ||
class CGInternal(CGError): pass | ||
|
||
def mbuild(width, height): | ||
"""Build a NxN matrix filled with 0.""" | ||
result = list() | ||
for i in range(height): | ||
result.append(list()) | ||
for j in range(width): | ||
result[i].append(0.0) | ||
return result | ||
"""Build a NxN matrix filled with 0.""" | ||
result = list() | ||
for i in range(height): | ||
result.append(list()) | ||
for j in range(width): | ||
result[i].append(0.0) | ||
return result | ||
|
||
|
||
def mdump(matrix): | ||
"""Dump a matrix in natural format.""" | ||
for col in matrix: | ||
print("[ ", end = ''); | ||
for ele in col: | ||
print(format(ele, "13.6g") + ", ", end = " ") | ||
print("],") | ||
"""Dump a matrix in natural format.""" | ||
for col in matrix: | ||
print("[ ", end='') | ||
for ele in col: | ||
print(format(ele, "13.6g") + ", ", end=" ") | ||
print("],") | ||
|
||
|
||
def mdumpcompton(matrix): | ||
"""Dump a matrix in compton's format.""" | ||
width = len(matrix[0]) | ||
height = len(matrix) | ||
print("{},{},".format(width, height), end = '') | ||
for i in range(height): | ||
for j in range(width): | ||
if int(height / 2) == i and int(width / 2) == j: | ||
continue; | ||
print(format(matrix[i][j], ".6f"), end = ",") | ||
print() | ||
"""Dump a matrix in compton's format.""" | ||
width = len(matrix[0]) | ||
height = len(matrix) | ||
print("{},{},".format(width, height), end='') | ||
for i in range(height): | ||
for j in range(width): | ||
if int(height / 2) == i and int(width / 2) == j: | ||
continue | ||
print(format(matrix[i][j], ".6f"), end=",") | ||
print() | ||
|
||
|
||
def mnormalize(matrix): | ||
"""Scale a matrix according to the value in the center.""" | ||
width = len(matrix[0]) | ||
height = len(matrix) | ||
factor = 1.0 / matrix[int(height / 2)][int(width / 2)] | ||
if 1.0 == factor: return matrix | ||
for i in range(height): | ||
for j in range(width): | ||
matrix[i][j] *= factor | ||
return matrix | ||
"""Scale a matrix according to the value in the center.""" | ||
width = len(matrix[0]) | ||
height = len(matrix) | ||
factor = 1.0 / matrix[int(height / 2)][int(width / 2)] | ||
if 1.0 == factor: | ||
return matrix | ||
for i in range(height): | ||
for j in range(width): | ||
matrix[i][j] *= factor | ||
return matrix | ||
|
||
|
||
def mmirror4(matrix): | ||
"""Do a 4-way mirroring on a matrix from top-left corner.""" | ||
width = len(matrix[0]) | ||
height = len(matrix) | ||
for i in range(height): | ||
for j in range(width): | ||
x = min(i, height - 1 - i) | ||
y = min(j, width - 1 - j) | ||
matrix[i][j] = matrix[x][y] | ||
return matrix | ||
"""Do a 4-way mirroring on a matrix from top-left corner.""" | ||
width = len(matrix[0]) | ||
height = len(matrix) | ||
for i in range(height): | ||
for j in range(width): | ||
x = min(i, height - 1 - i) | ||
y = min(j, width - 1 - j) | ||
matrix[i][j] = matrix[x][y] | ||
return matrix | ||
|
||
|
||
def gen_gaussian(width, height, factors): | ||
"""Build a Gaussian blur kernel.""" | ||
"""Build a Gaussian blur kernel.""" | ||
|
||
if width != height: | ||
raise CGBadArg("Cannot build an uneven Gaussian blur kernel.") | ||
|
||
if width != height: | ||
raise CGBadArg("Cannot build an uneven Gaussian blur kernel.") | ||
size = width | ||
sigma = float(factors.get('sigma', 0.84089642)) | ||
|
||
size = width | ||
sigma = float(factors.get('sigma', 0.84089642)) | ||
result = mbuild(size, size) | ||
for i in range(int(size / 2) + 1): | ||
for j in range(int(size / 2) + 1): | ||
diffx = i - int(size / 2) | ||
diffy = j - int(size / 2) | ||
result[i][j] = 1.0 / (2 * math.pi * sigma) \ | ||
* pow(math.e, - (diffx * diffx + diffy * diffy) \ | ||
/ (2 * sigma * sigma)) | ||
mnormalize(result) | ||
mmirror4(result) | ||
|
||
result = mbuild(size, size) | ||
for i in range(int(size / 2) + 1): | ||
for j in range(int(size / 2) + 1): | ||
diffx = i - int(size / 2); | ||
diffy = j - int(size / 2); | ||
result[i][j] = 1.0 / (2 * math.pi * sigma) * pow(math.e, - (diffx * diffx + diffy * diffy) / (2 * sigma * sigma)) | ||
mnormalize(result) | ||
mmirror4(result) | ||
return result | ||
|
||
return result | ||
|
||
def gen_box(width, height, factors): | ||
"""Build a box blur kernel.""" | ||
result = mbuild(width, height) | ||
for i in range(height): | ||
for j in range(width): | ||
result[i][j] = 1.0 | ||
return result | ||
|
||
def gen_invalid(width, height, factors): | ||
raise CGBadArg("Unknown kernel type.") | ||
|
||
def args_readfactors(lst): | ||
"""Parse the factor arguments.""" | ||
factors = dict() | ||
if lst: | ||
for s in lst: | ||
res = s.partition('=') | ||
if not res[0]: | ||
raise CGBadArg("Factor has no key.") | ||
if not res[2]: | ||
raise CGBadArg("Factor has no value.") | ||
factors[res[0]] = float(res[2]) | ||
return factors | ||
|
||
parser = argparse.ArgumentParser(description='Build a convolution kernel.') | ||
parser.add_argument('type', help='Type of convolution kernel. May be "gaussian" (factor sigma = 0.84089642) or "box".') | ||
parser.add_argument('width', type=int, help='Width of convolution kernel. Must be an odd number.') | ||
parser.add_argument('height', nargs='?', type=int, help='Height of convolution kernel. Must be an odd number. Equals to width if omitted.') | ||
parser.add_argument('-f', '--factor', nargs='+', help='Factors of the convolution kernel, in name=value format.') | ||
parser.add_argument('--dump-compton', action='store_true', help='Dump in compton format.') | ||
args = parser.parse_args() | ||
|
||
width = args.width | ||
height = args.height | ||
if not height: | ||
height = width | ||
if not (width > 0 and height > 0): | ||
raise CGBadArg("Invalid width/height.") | ||
factors = args_readfactors(args.factor) | ||
|
||
funcs = dict(gaussian = gen_gaussian, box = gen_box) | ||
matrix = (funcs.get(args.type, gen_invalid))(width, height, factors) | ||
if args.dump_compton: | ||
mdumpcompton(matrix) | ||
else: | ||
mdump(matrix) | ||
"""Build a box blur kernel.""" | ||
result = mbuild(width, height) | ||
for i in range(height): | ||
for j in range(width): | ||
result[i][j] = 1.0 | ||
return result | ||
|
||
|
||
def _gen_invalid(width, height, factors): | ||
'''Handle a convolution kernel generation request of an unrecognized type.''' | ||
raise CGBadArg("Unknown kernel type.") | ||
|
||
|
||
def _args_readfactors(lst): | ||
"""Parse the factor arguments.""" | ||
factors = dict() | ||
if lst: | ||
for s in lst: | ||
res = s.partition('=') | ||
if not res[0]: | ||
raise CGBadArg("Factor has no key.") | ||
if not res[2]: | ||
raise CGBadArg("Factor has no value.") | ||
factors[res[0]] = float(res[2]) | ||
return factors | ||
|
||
|
||
def _parse_args(): | ||
'''Parse the command-line arguments.''' | ||
|
||
parser = argparse.ArgumentParser(description='Build a convolution kernel.') | ||
parser.add_argument('type', help='Type of convolution kernel. May be "gaussian" (factor sigma = 0.84089642) or "box".') | ||
parser.add_argument('width', type=int, help='Width of convolution kernel. Must be an odd number.') | ||
parser.add_argument('height', nargs='?', type=int, help='Height of convolution kernel. Must be an odd number. Equals to width if omitted.') | ||
parser.add_argument('-f', '--factor', nargs='+', help='Factors of the convolution kernel, in name=value format.') | ||
parser.add_argument('--dump-compton', action='store_true', help='Dump in compton format.') | ||
return parser.parse_args() | ||
|
||
|
||
def _main(): | ||
args = _parse_args() | ||
|
||
width = args.width | ||
height = args.height | ||
if not height: | ||
height = width | ||
if not (width > 0 and height > 0): | ||
raise CGBadArg("Invalid width/height.") | ||
factors = _args_readfactors(args.factor) | ||
|
||
funcs = dict(gaussian=gen_gaussian, box=gen_box) | ||
matrix = (funcs.get(args.type, _gen_invalid))(width, height, factors) | ||
if args.dump_compton: | ||
mdumpcompton(matrix) | ||
else: | ||
mdump(matrix) | ||
|
||
|
||
if __name__ == '__main__': | ||
_main() |