From 939ba64791f43efd074e3bf26d94dfc4691612ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rostislav=20L=C3=A1n?= Date: Tue, 7 Mar 2023 14:13:07 +0100 Subject: [PATCH] Added basic operations - binarization, scaling of image values and margin around image. --- src/filters.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/main.py | 17 +++++++---------- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/filters.py b/src/filters.py index e302af5..e1f8427 100644 --- a/src/filters.py +++ b/src/filters.py @@ -8,6 +8,7 @@ import cv2 as cv from skimage import filters as skiflt from skimage import restoration as skirest #from scipy import signal as sig +from PIL import Image, ImageFilter # Parent class for all the filters @@ -110,6 +111,53 @@ class bilateral(filter): self.img = cv.bilateralFilter(self.img, d, sigmaColor, sigmaSpace) +class scale_values(filter): + ''' Scale values of the image to use the entire range of data type. + This should remove the line height issues. + ''' + def __init__(self, img): + super().__init__(img) + + def apply(self, params): + # do this once for inverted image and once for original + # this is done to get whiter whites and blacker blacks + # which helps to get exact line height on stl model + tmp = cv.bitwise_not(self.img.astype(np.uint8)) + coef = 255 / np.max(tmp) + tmp = tmp * coef + self.img = cv.bitwise_not(tmp.astype(np.uint8)) + coef = 255 / np.max(tmp) + tmp = tmp * coef + + +class binarize(filter): + def init(self, img): + super().__init__(img) + + def apply(self, params): + threshold = int(params["threshold"]) if params["threshold"] else 128 + maxval = int(params["maxval"]) if params["maxval"] else 255 + type = int(params["type"]) if params["type"] else 0 + + #print("with params: threshold: " + str(threshold) + + # " maxval: " + str(maxval) + " type: " + str(type)) + self.img = cv.threshold(self.img, threshold, maxval, type)[1] + + +class add_margin(filter): + def init(self, img): + super().__init__(img) + + def apply(self, params): + margin = int(params["margin"]) if params["margin"] else 10 + color = int(params["color"]) if params["color"] else 255 + self.fig.set_size_inches( + ((self.width + 2 * margin) / self.dpi, (self.height + 2 * margin) / self.dpi)) + self.img = cv.copyMakeBorder( + self.img, margin, margin, margin, margin, cv.BORDER_CONSTANT, value=color) + self.height, self.width = self.img.shape + + class denoise(filter): # TODO possibly not necessary def __init__(self, img): @@ -263,6 +311,7 @@ class morph(filter): super().__init__(img) def apply(self, params): + # TODO: this is probably better with binarized image kernel = np.matrix(params["kernel"]) if params["kernel"] else np.ones( (3, 3), np.uint8) iterations = int(params["iterations"]) if params["iterations"] else 1 diff --git a/src/main.py b/src/main.py index 2743c31..105aa96 100644 --- a/src/main.py +++ b/src/main.py @@ -7,7 +7,6 @@ import argparse as ap import sys import json -import math from os.path import exists # Libraries for image processing @@ -159,7 +158,8 @@ class app: "ksize", "kernel", "sigmaX", "sigmaY", "sigmaColor", "sigmaSpace", "d", "anchor", "iterations", "op", "strength", "amount", "radius", "weight", "channelAxis", - "theta", "sigma", "lambda", "gamma", "psi", "shape", "percent", "threshold"} + "theta", "sigma", "lambda", "gamma", "psi", "shape", "percent", + "threshold", "maxval", "type", "margin", "color"} for key in possible_params: if params.get(key) is None: @@ -208,17 +208,14 @@ class app: # gets empty figure and ax with dimensions of input image self.height, self.width = self.img.shape - fig, ax = self.get_empty_figure() + self.fig, ax = self.get_empty_figure() - # print("Height: " + str(self.height) + " px and width: " - # + str(self.width) + " px", file=sys.stderr) - if self.mirror is True: self.mirror_image() # Apply all filters and save image self.apply_filters() - self.save_image(fig, ax) + self.save_image(self.fig, ax) plt.close() def get_empty_figure(self): @@ -260,7 +257,7 @@ class app: # Colormap must be set to grayscale to avoid color mismatch. ax.imshow(self.img, cmap="gray") - fig.savefig(fname=self.output_file, dpi=self.dpi) + fig.savefig(fname=self.output_file) #------------------------- STL GENERATION -------------------------# @@ -336,8 +333,7 @@ class app: ''' # TODO: somehow compress this to fit it onto the model - self.id = self.input_file.split( - "/")[-1].split(".")[0] + "_" + self.preset_name + self.id = self.input_file.split("/")[-1].split(".")[0] + "_" + self.preset_name # TODO: hash is not unique, find a better way # TODO: stl file format has 80 chars for header, use that space to store info # python generates a random value for security reasons, it has to be turned off @@ -615,6 +611,7 @@ class app: def save_stl(self): '''Save final mesh to stl file. ''' + # TODO: add a hash function to create ID specific to # input image + preset from config. file or from console + input params # TODO: add the full parameters and filters to a file inside output dir.