From 84216a960fd7a1334db3d5d519dfb72a0671a55a Mon Sep 17 00:00:00 2001 From: WANG Date: Wed, 4 Sep 2013 17:31:23 +0200 Subject: [PATCH 1/1] Parameterize the licenceplate algorithm in architecture/morpho.lib. --- architecture/morpho.lib | 44 +++-- examples/licenseplate/licenceplate.dsp | 6 +- examples/licenseplate/licenceplate.sh | 2 +- examples/licenseplate/output1.bmp | Bin 68850 -> 0 bytes examples/licenseplate/output1.csv | 234 ++++++++++++------------- 5 files changed, 154 insertions(+), 132 deletions(-) delete mode 100644 examples/licenseplate/output1.bmp diff --git a/architecture/morpho.lib b/architecture/morpho.lib index 7d86d47..6741f36 100644 --- a/architecture/morpho.lib +++ b/architecture/morpho.lib @@ -17,33 +17,51 @@ tri_mins(n) = par(i, n, tri_min); dilating(n) = strel_shift_dilation, _, strel_shift_dilation : #, _ : # : spray_by_three(n) : tri_maxs(n) : nconcat(n); eroding(n) = strel_shift_erosion, _, strel_shift_erosion : #, _ : # : spray_by_three(n) : tri_mins(n) : nconcat(n); -//dilation(size, iter) = seq(i, iter, dilating(size)); -//erosion(size, iter) = seq(i, iter, eroding(size)); +dilation_line(x, y) = serialize : dilating(x) : vectorize(y); +erosion_line(x, y) = serialize : eroding(x) : vectorize(y); -dilation_square(x, y) = serialize : dilating(x) : vectorize(y) : matrix_transpose(y, x) : serialize : dilating(y) : vectorize(x) : matrix_transpose(x, y); +dilation_column(x, y) = matrix_transpose(y, x) : serialize : dilating(y) : vectorize(x) : matrix_transpose(x, y); +erosion_column(x, y) = matrix_transpose(y, x) : serialize : eroding(y) : vectorize(x) : matrix_transpose(x, y); -erosion_square(x, y) = serialize : eroding(x) : vectorize(y) : matrix_transpose(y, x) : serialize : eroding(y) : vectorize(x) : matrix_transpose(x, y); +dilation_square(x, y) = dilation_line(x, y) : dilation_column(x, y); +erosion_square(x, y) = erosion_line(x, y) : erosion_column(x, y); cross = _, _ <: !, _, _, !; -//dilations(x, y, iter) = seq(i, iter, dilation_square(x,y)); -//erosions(x, y, iter) = seq(i, iter, erosion_square(x,y)); +dilations_line(x, y, iter) = _ : vectorize(y) : (iter, ((cross : ((0, 1 : prefix), _, _ : select2) : dilation_line(x, y))~_), (iter - 1)) : rdtable : serialize; -dilations(x, y, iter) = _ : vectorize(y) : (iter, ((cross : ((0, 1 : prefix), _, _ : select2) : dilation_square(x, y))~_), (iter - 1)) : rdtable : serialize; -erosions(x, y, iter) = _ : vectorize(y) : (iter, ((cross : ((0, 1 : prefix), _, _ : select2) : erosion_square(x, y))~_), (iter - 1)) : rdtable : serialize; +erosions_line(x, y, iter) = _ : vectorize(y) : (iter, ((cross : ((0, 1 : prefix), _, _ : select2) : erosion_line(x, y))~_), (iter - 1)) : rdtable : serialize; -opening(x, y, iter) = erosions(x, y, iter) : dilations(x, y, iter); -closing(x, y, iter) = dilations(x, y, iter) : erosions(x, y, iter); +dilations_column(x, y, iter) = _ : vectorize(y) : (iter, ((cross : ((0, 1 : prefix), _, _ : select2) : dilation_column(x, y))~_), (iter - 1)) : rdtable : serialize; + +erosions_column(x, y, iter) = _ : vectorize(y) : (iter, ((cross : ((0, 1 : prefix), _, _ : select2) : erosion_column(x, y))~_), (iter - 1)) : rdtable : serialize; + +dilations_square(x, y, iter) = _ : vectorize(y) : (iter, ((cross : ((0, 1 : prefix), _, _ : select2) : dilation_square(x, y))~_), (iter - 1)) : rdtable : serialize; + +erosions_square(x, y, iter) = _ : vectorize(y) : (iter, ((cross : ((0, 1 : prefix), _, _ : select2) : erosion_square(x, y))~_), (iter - 1)) : rdtable : serialize; + +opening_line(x, y, iter) = erosions_line(x, y, iter) : dilations_line(x, y, iter); +closing_line(x, y, iter) = dilations_line(x, y, iter) : erosions_line(x, y, iter); + +opening_column(x, y, iter) = erosions_column(x, y, iter) : dilations_column(x, y, iter); +closing_column(x, y, iter) = dilations_column(x, y, iter) : erosions_column(x, y, iter); + +opening_square(x, y, iter) = erosions_square(x, y, iter) : dilations_square(x, y, iter); +closing_square(x, y, iter) = dilations_square(x, y, iter) : erosions_square(x, y, iter); -threshold(x, n) = _, (n : vectorize(x)) : >; and = *; +threshold(x, low, high) = _ <: (_, (low : vectorize(x)) : >), (_, (high : vectorize(x)) : <) : and; + +//licenceplate(x, y) = _ <: (opening_line(x, y, 15), closing_line(x, y, 8) : threshold(x, 1, 50), threshold(x, 150, 255) : and : opening_column(x, y, 4) : opening_line(x, y, 4) : dilations_square(x, y, 2)), _ : and; + +licenceplate(x, y, o1, c2, t3, t4, t5, t6, o7, o8, d9) = _ <: (opening_line(x, y, o1), closing_line(x, y, c2) : threshold(x, t3, t4), threshold(x, t5, t6) : and : opening_column(x, y, o7) : opening_line(x, y, o8) : dilations_square(x, y, d9)), _ : and; -licenceplate(x, y, seuil) = _ <: (opening(x, y, 1), closing(x, y, 1) : threshold(x, seuil), threshold(x, seuil) : and : opening(x, y, 1) : dilations(x, y, 1)), _ : and; +//licenceplate(x, y) = _ <: (opening_line(x, y, 4), closing_line(x, y, 2) : threshold(x, 1, 50), threshold(x, 150, 255) : and : opening_column(x, y, 4) : opening_line(x, y, 4) : dilations_square(x, y, 4)), _ : and; //process = dilations(8, 8, 3); //process = erosions(8, 8, 3); //process = open(8, 8, 2); //process = close(8, 8, 5); -//process = licenceplate(8, 8, 128); +//process = licenceplate(4, 4, 15, 8, 1, 50, 150, 255, 4, 4, 2); diff --git a/examples/licenseplate/licenceplate.dsp b/examples/licenseplate/licenceplate.dsp index 45013db..4ade83c 100644 --- a/examples/licenseplate/licenceplate.dsp +++ b/examples/licenseplate/licenceplate.dsp @@ -1,3 +1,7 @@ import ("../../architecture/morpho.lib"); -process = licenceplate(195, 117, 128); +process = licenceplate(640, 383, 15, 8, 1, 50, 150, 255, 4, 4, 2); + +//process = licenceplate(195, 117, 1, 4, 1, 50, 150, 255, 1, 1, 2); + +//process = licenceplate(195, 117); diff --git a/examples/licenseplate/licenceplate.sh b/examples/licenseplate/licenceplate.sh index 01a6cf3..01e40c8 100644 --- a/examples/licenseplate/licenceplate.sh +++ b/examples/licenseplate/licenceplate.sh @@ -1 +1 @@ -../../interpretor/faustine -d licenceplate.dsp -i licence_small.csv -t 117 --oformat csv +../../interpretor/faustine -d licenceplate.dsp -i licence.csv -t 383 --oformat csv diff --git a/examples/licenseplate/output1.bmp b/examples/licenseplate/output1.bmp deleted file mode 100644 index 51b8116904cd2f3f36fe7dad4c3f5c6ed8dfc150..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68850 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 fc`&Kb