Skip to content

Commit

Permalink
Merge pull request #99 from libmir/new_ndslice
Browse files Browse the repository at this point in the history
New ndslice
  • Loading branch information
ljubobratovicrelja authored Mar 1, 2017
2 parents 030a71b + edbbe07 commit a2dfdf5
Show file tree
Hide file tree
Showing 32 changed files with 1,224 additions and 1,248 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ dub.userprefs
*.lst
__test__*
libdcv*.a

*.sublime-project
*.o
.DS_Store
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ os:
- linux

d:
- ldc-1.1.0-beta5
- ldc-1.1.0
- dmd-2.072.0

addons:
apt:
Expand Down
7 changes: 4 additions & 3 deletions dub.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
],
"dependencies":
{
"mir": "~>0.22.0"
"mir-math": "~>0.0.1",
"mir-algorithm": "~>0.0.25"
}
},
{
Expand All @@ -59,7 +60,7 @@
"source/dcv/io"
],
"dependencies":{
"dcv:core": ">=0.0.0",
"dcv:core": "*",
"imageformats": "~>6.1.0",
"ffmpeg-d": "~>2.5.1"
}
Expand All @@ -71,7 +72,7 @@
"source/dcv/plot"
],
"dependencies":{
"dcv:core": ">=0.0.0"
"dcv:core": "*"
},
"configurations":
[
Expand Down
36 changes: 17 additions & 19 deletions examples/features/source/app.d
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
module dcv.example.imgmanip;

/**
/**
* Corner extraction example, by using Harris and Shi-Tomasi algorithms.
*/

import std.stdio;
import mir.ndslice;
import std.array : array;
import std.algorithm.iteration : map, reduce;
import std.range : repeat;

import dcv.core;
import dcv.features;
Expand All @@ -21,6 +17,7 @@ import ggplotd.ggplotd;
import ggplotd.geom;
import ggplotd.aes;


void main()
{
// read source image
Expand All @@ -33,18 +30,16 @@ void main()

// make copies to draw corners
auto pixelSize = imslice.elementsCount;
auto shiTomasiDraw = new ubyte[pixelSize].sliced(imslice.shape);
auto harrisDraw = new ubyte[pixelSize].sliced(imslice.shape);
shiTomasiDraw[] = imslice[];
harrisDraw[] = imslice[];
auto shiTomasiDraw = imslice.slice;
auto harrisDraw = imslice.slice;

// estimate corner response for each of corner algorithms by using 5x5 window.
auto shiTomasiResponse = shiTomasiCorners(gray, 5).filterNonMaximum;
auto harrisResponse = harrisCorners(gray, 5).filterNonMaximum;

// extract corners from the response matrix ( extract 100 corners, where each response is larger than 0.)
auto shiTomasiCorners = extractCorners(shiTomasiResponse, 100, 0.);
auto harrisCorners = extractCorners(harrisResponse, 100, 0.);
auto shiTomasiCorners = extractCorners(shiTomasiResponse, 100, 0.0f);
auto harrisCorners = extractCorners(harrisResponse, 100, 0.0f);

// visualize corner response, and write it to disk.
visualizeCornerResponse(harrisResponse, "harrisResponse");
Expand All @@ -57,11 +52,11 @@ void main()
waitKey();
}

void visualizeCornerResponse(Slice!(2, float*) response, string windowName)
void visualizeCornerResponse(SliceKind kind)(Slice!(kind, [2], float*) response, string windowName)
{
response
response
// scale values in the response matrix for easier visualization.
.ranged(0., 255.)
.ranged(0f, 255f)
.as!ubyte
.slice
// Show the window
Expand All @@ -71,14 +66,17 @@ void visualizeCornerResponse(Slice!(2, float*) response, string windowName)
.imwrite("result/" ~ windowName ~ ".png");
}

void cornerPlot(Slice!(3, ubyte*) slice, ulong[2][] corners, string windowName)
void cornerPlot(SliceKind kind)(Slice!(kind, [3], ubyte*) slice, size_t[2][] corners, string windowName)
{
import std.array : array;
import std.algorithm.iteration : map;

// separate coordinate values
auto xs = corners.map!(v => v[1]);
auto ys = corners.map!(v => v[0]);
auto xs = corners.map!(e => e[1]);
auto ys = corners.map!(e => e[0]);

auto aes = Aes!(typeof(xs), "x", typeof(ys), "y", bool[], "fill", string[], "colour")(xs, ys,
false.repeat(xs.length).array, "red".repeat(xs.length).array);
auto aes = Aes!(typeof(xs), "x", typeof(ys), "y", bool[], "fill", string[], "colour")
(xs, ys, false.repeat(xs.length).array, "red".repeat(xs.length).array);

auto gg = GGPlotD().put(geomPoint(aes));

Expand Down
35 changes: 21 additions & 14 deletions examples/filter/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ module dcv.example.convolution;

import std.stdio : writeln;
import std.datetime : StopWatch;
import std.math : fabs;
import std.math : abs;
import std.array : array;
import std.algorithm.iteration : map;

import mir.ndslice;

Expand All @@ -29,7 +28,7 @@ int main(string[] args)
return 1;
}

Slice!(3, float*) imslice = img
Slice!(Contiguous, [3], float*) imslice = img
.sliced // slice image data
.as!float // convert it to float
.slice; // make a copy.
Expand All @@ -39,20 +38,19 @@ int main(string[] args)
auto gaussianKernel = gaussian!float(2, 5, 5); // create gaussian convolution kernel (sigma, kernel width and height)
auto sobelXKernel = sobel!real(GradientDirection.DIR_X); // sobel operator for horizontal (X) gradients
auto laplacianKernel = laplacian!double; // laplacian kernel, similar to matlabs fspecial('laplacian', alpha)
auto logKernel = laplacianOfGaussian(1, 5, 5); // laplacian of gaussian, similar to matlabs fspecial('log', alpha, width, height)
auto logKernel = laplacianOfGaussian!float(1, 5, 5); // laplacian of gaussian, similar to matlabs fspecial('log', alpha, width, height)

// perform convolution for each kernel
auto blur = imslice.conv(gaussianKernel);
auto xgrads = gray.conv(sobelXKernel);
auto laplaceEdges = gray.conv(laplacianKernel);
auto logEdges = gray.conv(logKernel);


// calculate canny edges
auto cannyEdges = gray.canny!ubyte(75);

// perform bilateral blurring
auto bilBlur = imslice.bilateralFilter(10.0f, 10.0f, 5);
auto bilBlur = imslice.bilateralFilter!float(10.0f, 10.0f, 5);

// Add salt and pepper noise at input image green channel
auto noisyImage = imslice.slice;
Expand All @@ -63,8 +61,8 @@ int main(string[] args)
// scale values from 0 to 255 to preview gradient direction and magnitude
xgrads.ranged(0, 255);
// Take absolute values and range them from 0 to 255, to preview edges
laplaceEdges = laplaceEdges.ndMap!(a => fabs(a)).slice.ranged(0.0f, 255.0f);
logEdges = logEdges.ndMap!(a => fabs(a)).slice.ranged(0.0f, 255.0f);
laplaceEdges = laplaceEdges.map!(a => abs(a)).slice.ranged(0.0f, 255.0f);
logEdges = logEdges.map!(a => abs(a)).slice.ranged(0.0f, 255.0f);

// Show images on screen
img.imshow("Original");
Expand All @@ -82,20 +80,29 @@ int main(string[] args)
return 0;
}

Slice!(2, T*) saltNPepper(T)(Slice!(2, T*) slice, float saturation)
auto saltNPepper(T, SliceKind kind)(Slice!(kind, [2], T*) input, float saturation)
{
import std.range, std.random;
import std.range : lockstep;
import std.random : uniform;

ulong pixelCount = slice.length!0*slice.length!1;
int err;
ulong pixelCount = input.length!0*input.length!1;
ulong noisyPixelCount = cast(typeof(pixelCount))(pixelCount * saturation);

auto noisyPixels = noisyPixelCount.iota.map!(x => uniform(0, pixelCount)).array;
auto imdata = slice.reshape(pixelCount);
auto noisyPixels = slice!size_t(noisyPixelCount);
foreach(ref e; noisyPixels)
{
e = uniform(0, pixelCount);
}

auto imdata = input.reshape([pixelCount], err);

assert(err == 0);

foreach(salt, pepper; lockstep(noisyPixels[0 .. $ / 2], noisyPixels[$ / 2 .. $]))
{
imdata[salt] = cast(T)255;
imdata[pepper] = cast(T)0;
}
return slice;
return input;
}
12 changes: 6 additions & 6 deletions examples/rht/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import dcv.io : imread, imwrite;
import dcv.imgproc;
import dcv.features.rht;

void plotLine(T, Line, Color)(Slice!(3, T*) img, Line line, Color color)
void plotLine(T, Line, Color)(Slice!(Contiguous, [3], T*) img, Line line, Color color)
{
int height = cast(int)img.length!0;
int width = cast(int)img.length!1;
Expand All @@ -43,7 +43,7 @@ void plotLine(T, Line, Color)(Slice!(3, T*) img, Line line, Color color)
}
}

void plotCircle(T, Circle, Color)(Slice!(3, T*) img, Circle circle, Color color)
void plotCircle(T, Circle, Color)(Slice!(Contiguous, [3], T*) img, Circle circle, Color color)
{
int height = cast(int)img.length!0;
int width = cast(int)img.length!1;
Expand All @@ -70,7 +70,7 @@ int main(string[] args)
return 1;
}

Slice!(3, float*) imslice = img.sliced.as!float.slice; // convert Image data type from ubyte to float
Slice!(Contiguous, [3], float*) imslice = img.sliced.as!float.slice; // convert Image data type from ubyte to float

auto gray = imslice.rgb2gray; // convert rgb image to grayscale

Expand Down Expand Up @@ -103,9 +103,9 @@ int main(string[] args)
writeln("RHT circles took ", s.peek.msecs, "ms");

// write resulting images on the filesystem.
blur.ndMap!(v => v.clip!ubyte).slice.imwrite(ImageFormat.IF_RGB, "./result/outblur.png");
canny.ndMap!(v => v.clip!ubyte).slice.imwrite(ImageFormat.IF_MONO, "./result/canny.png");
imslice.ndMap!(v => v.clip!ubyte).slice.imwrite(ImageFormat.IF_RGB, "./result/rht.png");
blur.map!(v => v.clip!ubyte).slice.imwrite(ImageFormat.IF_RGB, "./result/outblur.png");
canny.map!(v => v.clip!ubyte).slice.imwrite(ImageFormat.IF_MONO, "./result/canny.png");
imslice.map!(v => v.clip!ubyte).slice.imwrite(ImageFormat.IF_RGB, "./result/rht.png");

return 0;
}
5 changes: 3 additions & 2 deletions examples/stereo/source/app.d
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
module dcv.example.stereo;

import std.algorithm;
import std.math;
import std.range;
import std.stdio;

import mir.ndslice.algorithm : reduce;

import dcv.imgproc;
import dcv.io.image;
import dcv.plot;
Expand Down Expand Up @@ -49,7 +50,7 @@ void main(string[] args)
}
}

auto acc = ndReduce!(evalAccum)(0.0f, estimate, groundTruth.sliced.rgb2gray);
auto acc = reduce!(evalAccum)(0.0f, estimate, groundTruth.sliced.rgb2gray);

writeln((acc / cast(float)c) * 100, "% accuracy (<=3px)");

Expand Down
9 changes: 7 additions & 2 deletions examples/tracking/klt/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,12 @@ int main(string[] args)
if (corners.length < (cornerCount / 2))
{
writeln("Search features again...");
auto c = shiTomasiCorners(prevFrame.sliced.reshape(h, w).as!float.slice, cast(uint)cornerW)
int err;
auto c = shiTomasiCorners(prevFrame.sliced.reshape([h, w], err).as!float.slice, cast(uint)cornerW)
.filterNonMaximum.extractCorners(cornerCount);

assert(err == 0);

foreach (v; c)
corners ~= [cast(float)v[0], cast(float)v[1]];
}
Expand Down Expand Up @@ -176,7 +179,9 @@ int main(string[] args)
}

// draw tracked corners and write the image
auto f2c = thisFrame.sliced.reshape(h, w).gray2rgb.as!float.slice;
int err;
auto f2c = thisFrame.sliced.reshape([h, w], err).gray2rgb.as!float.slice;
assert(err == 0);

// plot tracked points on screen.
f2c.plot(plotPoints(corners), "KLT");
Expand Down
Loading

0 comments on commit a2dfdf5

Please sign in to comment.