Added basic operations - binarization, scaling of image values and margin around image.
This commit is contained in:
@ -8,6 +8,7 @@ import cv2 as cv
|
|||||||
from skimage import filters as skiflt
|
from skimage import filters as skiflt
|
||||||
from skimage import restoration as skirest
|
from skimage import restoration as skirest
|
||||||
#from scipy import signal as sig
|
#from scipy import signal as sig
|
||||||
|
from PIL import Image, ImageFilter
|
||||||
|
|
||||||
|
|
||||||
# Parent class for all the filters
|
# Parent class for all the filters
|
||||||
@ -110,6 +111,53 @@ class bilateral(filter):
|
|||||||
self.img = cv.bilateralFilter(self.img, d, sigmaColor, sigmaSpace)
|
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):
|
class denoise(filter):
|
||||||
# TODO possibly not necessary
|
# TODO possibly not necessary
|
||||||
def __init__(self, img):
|
def __init__(self, img):
|
||||||
@ -263,6 +311,7 @@ class morph(filter):
|
|||||||
super().__init__(img)
|
super().__init__(img)
|
||||||
|
|
||||||
def apply(self, params):
|
def apply(self, params):
|
||||||
|
# TODO: this is probably better with binarized image
|
||||||
kernel = np.matrix(params["kernel"]) if params["kernel"] else np.ones(
|
kernel = np.matrix(params["kernel"]) if params["kernel"] else np.ones(
|
||||||
(3, 3), np.uint8)
|
(3, 3), np.uint8)
|
||||||
iterations = int(params["iterations"]) if params["iterations"] else 1
|
iterations = int(params["iterations"]) if params["iterations"] else 1
|
||||||
|
17
src/main.py
17
src/main.py
@ -7,7 +7,6 @@
|
|||||||
import argparse as ap
|
import argparse as ap
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import math
|
|
||||||
from os.path import exists
|
from os.path import exists
|
||||||
|
|
||||||
# Libraries for image processing
|
# Libraries for image processing
|
||||||
@ -159,7 +158,8 @@ class app:
|
|||||||
"ksize", "kernel", "sigmaX", "sigmaY",
|
"ksize", "kernel", "sigmaX", "sigmaY",
|
||||||
"sigmaColor", "sigmaSpace", "d", "anchor", "iterations",
|
"sigmaColor", "sigmaSpace", "d", "anchor", "iterations",
|
||||||
"op", "strength", "amount", "radius", "weight", "channelAxis",
|
"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:
|
for key in possible_params:
|
||||||
if params.get(key) is None:
|
if params.get(key) is None:
|
||||||
@ -208,17 +208,14 @@ class app:
|
|||||||
|
|
||||||
# gets empty figure and ax with dimensions of input image
|
# gets empty figure and ax with dimensions of input image
|
||||||
self.height, self.width = self.img.shape
|
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:
|
if self.mirror is True:
|
||||||
self.mirror_image()
|
self.mirror_image()
|
||||||
|
|
||||||
# Apply all filters and save image
|
# Apply all filters and save image
|
||||||
self.apply_filters()
|
self.apply_filters()
|
||||||
self.save_image(fig, ax)
|
self.save_image(self.fig, ax)
|
||||||
plt.close()
|
plt.close()
|
||||||
|
|
||||||
def get_empty_figure(self):
|
def get_empty_figure(self):
|
||||||
@ -260,7 +257,7 @@ class app:
|
|||||||
|
|
||||||
# Colormap must be set to grayscale to avoid color mismatch.
|
# Colormap must be set to grayscale to avoid color mismatch.
|
||||||
ax.imshow(self.img, cmap="gray")
|
ax.imshow(self.img, cmap="gray")
|
||||||
fig.savefig(fname=self.output_file, dpi=self.dpi)
|
fig.savefig(fname=self.output_file)
|
||||||
|
|
||||||
#------------------------- STL GENERATION -------------------------#
|
#------------------------- STL GENERATION -------------------------#
|
||||||
|
|
||||||
@ -336,8 +333,7 @@ class app:
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
# TODO: somehow compress this to fit it onto the model
|
# TODO: somehow compress this to fit it onto the model
|
||||||
self.id = self.input_file.split(
|
self.id = self.input_file.split("/")[-1].split(".")[0] + "_" + self.preset_name
|
||||||
"/")[-1].split(".")[0] + "_" + self.preset_name
|
|
||||||
# TODO: hash is not unique, find a better way
|
# TODO: hash is not unique, find a better way
|
||||||
# TODO: stl file format has 80 chars for header, use that space to store info
|
# 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
|
# python generates a random value for security reasons, it has to be turned off
|
||||||
@ -615,6 +611,7 @@ class app:
|
|||||||
def save_stl(self):
|
def save_stl(self):
|
||||||
'''Save final mesh to stl file.
|
'''Save final mesh to stl file.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# TODO: add a hash function to create ID specific to
|
# TODO: add a hash function to create ID specific to
|
||||||
# input image + preset from config. file or from console + input params
|
# input image + preset from config. file or from console + input params
|
||||||
# TODO: add the full parameters and filters to a file inside output dir.
|
# TODO: add the full parameters and filters to a file inside output dir.
|
||||||
|
Reference in New Issue
Block a user