Möchte in einem Bild gerichtet Weichzeichnen,
wobei die Richtung gemäß der Senkrechten zur Kurve variable ist.
Die Bestimmung der Richtungen ect. habe ich schon erledigt,
nur die Performance des tatsächlichen Weichzeichnen lässt Wünsche offen.
Hier mein Code
Code: Alles auswählen
import numpy as np
import skimage.draw as skimDraw
def skimDrawLineFromKoords(koord1, koord2) :
return np.stack( ( skimDraw.line( \
koord1[0], koord1[1], \
koord2[0], koord2[1] \
) \
), axis=-1 )
degsAround = [-90., 90.]
partsBetween90deg = 6
degsDiff = degsAround[1] / np.round( \
degsAround[1] / ( 90. / partsBetween90deg ) \
)
blurFactorsCount = 6
def blurFactorsCreate():
# partMinimal = 1.0 / 24.0
partMinimal = 1.0 / 48.0
# partMaximal = 1.0 / 3.45
partMaximal = 1.0 / 24.0
n = blurFactorsCount
lsp = np.linspace(partMaximal, partMinimal, n)
return lsp / ( np.sum(lsp) * 2.0 ) # sum of factors == 0.5
# blurFactor, whose sum is 0.5
# blurFactors = np.array( [0.11111111, 0.1 , 0.08888889, 0.07777778, 0.06666667, 0.05555556] )
degTanVals = [] # list of degrees with their tangents
for deg in np.arange( \
degsAround[0] + degsDiff, degsAround[1] - 0.01 , degsDiff ) :
# tangents are corrected to be 1 at 45 degree
degTanVals.append( [ deg, \
(np.tan(np.radians(deg))) * ( 1. + np.finfo(np.float64).eps ) \
] )
degVarr = np.asarray( [li[0] for li in degTanVals])
tanVarr = np.asarray( [li[1] for li in degTanVals])
degMidDiff = degsDiff / 2. # difference of middle degree value to values in degVarr
# routines, which want to use the results of this method get following values:
degsForFilter = np.empty((degVarr.shape[0]+1))
degsForFilter[0] = degMidDiff + degsAround[0]
degsForFilter[1:] = degVarr + degMidDiff # each element in degVarr added by ...
# for return also vector components according the degees
# vector components assume a hypothenuse with length of 1000 pixels
blurFactors = blurFactorsCreate()
vektorKomponentsForBlurHypotLen = blurFactors.shape[0]
vektorKomponentsToDrawHypotLen = 10
def vektorKomponentsCreate():
countOf = blurFactorsCount
vektorKomponentsForBlurAll = np.empty( ( countOf, 2 ), dtype = np.int32 )
for d in range( countOf ) :
rad = np.radians(degsForFilter[d])
sin = np.sin(rad)
cos = np.cos(rad)
vektorKomponentsForBlurAll[d,0] = \
np.int32( np.round( vektorKomponentsForBlurHypotLen * sin ) )
vektorKomponentsForBlurAll[d,1] = \
np.int32( np.round( vektorKomponentsForBlurHypotLen * cos ) )
return vektorKomponentsForBlurAll
'''
for example:
vektorKomponentsForBlurAll = np.array( [
[-6, 1], [-6, 2], [-5, 4], [-4, 5], [-2, 6], [-1, 6],
[ 1, 6], [ 2, 6], [ 4, 5], [ 5, 4], [ 6, 2], [ 6, 1]
], dtype=np.int32 )
'''
def vektorLinesCreate() :
koord0 = np.array( [0,0], dtype=np.int32 )
lines = [ skimDrawLineFromKoords( koord0, vektorKomponentsForBlurAll[i] ) \
for i in range( vektorKomponentsForBlurAll.shape[0] ) ]
lengthToShorten = min([ lines[i].shape[0] for i in range( lines.__len__() ) ])
linesWithConter = np.empty( ( lines.__len__() * 2, lengthToShorten, 2), dtype=np.int32 )
# indices here : direction * 2 , number of point in line, koordinate
for i in range( lines.__len__() ) :
linesWithConter[ i * 2 ] = \
np.resize(lines[i],(lengthToShorten, lines[i].shape[1])) \
if lines[i].shape[0] > lengthToShorten \
else lines[i]
# lines in the opposite directions:
# 0, 2, 4 -> 1,3,5
linesWithConter[ i * 2 + 1] = linesWithConter[ i * 2 ] * -1
return linesWithConter
vektorKomponentsForBlurAll = vektorKomponentsCreate()
# all line coordinates involved to blur
linesWithConter = vektorLinesCreate()
# normally img_height and img_width are more then 100 times bigger
# then border_width
img_height = 23; img_width = 18
border_width = 7
rgb = np.arange(img_height * img_width * 3, dtype=np.uint8).reshape(img_height, img_width, 3)
rgbFlForAverage = np.stack( ( rgb.astype( np.float64 ), rgb.astype( np.float64 ) ) )
rgbFloat = rgbFlForAverage[0]
mask = np.zeros_like( rgb[:,:,0] )
mask_inner_selection = slice( border_width, -border_width )
mask_inner = mask[mask_inner_selection, mask_inner_selection]
mask_inner[:,:] = np.arange( mask_inner.shape[0] * mask_inner.shape[1], dtype=np.uint8 ). \
reshape( mask_inner.shape[0], mask_inner.shape[1] )
pxsKoordToFilter = np.asarray( np.where(mask > 0) )
# orientations_at_all has the calculated direction to filter with
orientations_at_all = np.zeros_like(mask)
orientations_at_all[:,:] = np.arange( img_height * img_width, dtype=np.uint8). \
reshape( img_height, img_width ) % partsBetween90deg
orientations_at_all[mask == 0] = 255 # 255 means not in mask
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# is it possible that the blur filter procedure performs better ? # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
for j in range( pxsKoordToFilter.shape[1] ) :
koord = pxsKoordToFilter[:,j]
koordTup = tuple(koord)
direction = orientations_at_all[koordTup]
rgbFloat[ koordTup ] = sum( [
rgb[ tuple( koord + linesWithConter[ direction * 2, i ] ) ] * blurFactors[i] + \
rgb[ tuple( koord + linesWithConter[ direction * 2 + 1, i ] ) ] * blurFactors[i] \
for i in range( blurFactors.shape[0] ) ] )
# weighted average in dependence of value in mask
rgbFloat[ koordTup ] *= mask[koordTup]
rgbFloat[ koordTup ] += rgbFlForAverage[1][koordTup] * \
( 255 - mask[koordTup] )
rgbFloat[ koordTup ] /= 255.0
rgb_blured = ( rgbFloat + 0.499 ).astype(np.uint8)