Anonymous user
Canny edge detector: Difference between revisions
More idiomatic D code
(Simpler D code) |
(More idiomatic D code) |
||
Line 419:
import std.math: PI, floor, exp, pow, hypot, fmod, atan2;
import std.typecons: tuple, Tuple;
import std.string: text;
enum MAX_BRIGHTNESS = 255;
Line 451 ⟶ 452:
Tuple!(Pixel[],BMPheader) loadBMP(in string fileName)
auto filePtr = fopen((fileName ~ "\0").ptr, "rb");
if (filePtr == null)
}▼
BMPheader header;
if (fread(&header, header.sizeof, 1, filePtr) != 1)
}▼
// verify that this is a bmp file by check bitmap id
if (header.smagic != 0x4D42)
}▼
if (header.compress_type != 0)
▲ fclose(filePtr);
}▼
// move file point to the beginning of bitmap data
Line 484 ⟶ 478:
foreach (ref bi; bitmapImage) {
ubyte c = void;
if (fread(&c, ubyte.sizeof, 1, filePtr) != 1)
}▼
bi = c;
}
fclose(filePtr);▼
return tuple(bitmapImage, header);
}
▲int saveBMP(in string fileName, const ref BMPheader header,
▲ scope(exit) if (filePtr) fclose(filePtr);
▲ in Pixel[] data) nothrow {
auto
if (filePtr ==
throw new Exception("saveBMP: fopen()");
immutable uint moffset = BMPheader.sizeof +
((1U << header.bitspp) * 4);
// generate
BMPheader newHeader = header;
newHeader.filesz = moffset + header.bmp_bytesz;
newHeader.bmp_offset = moffset;
fwrite(&newHeader, 1, newHeader.sizeof, fp);▼
throw new Exception("saveBMP: fwrite BMP header.");
//
foreach (i; 0 .. (1U << header.bitspp)) {
ubyte r, g, b,
▲ }
cast(ubyte)i);▼
fwrite(&color, 1, Rgb.sizeof, fp);▼
immutable colorEntry = Rgb(cast(ubyte)i,
cast(ubyte)i,
▲ cast(ubyte)i);
throw new Exception("saveBMP: fwrite palette.");
}
// write bitmap data
foreach (di; data) {
immutable ubyte c = cast(ubyte)di;
if (fwrite(&c, ubyte.sizeof, 1,
throw new Exception("saveBMP: fwrite bitmap data.");
}
}
// if
void convolution(bool normalize)(in Pixel[] inp, Pixel[] outp
pure nothrow {
immutable int khalf = kn / 2;
float pMin = float.max, pMax = -float.max;
static if (
foreach (m; khalf .. nx - khalf) {
foreach (n; khalf .. ny - khalf) {
float pixel = 0.0;
int c;
foreach (j; -khalf .. khalf + 1) {
foreach (i; -khalf .. khalf + 1) {
pixel += inp[(n - j) * nx + m - i] * kernel[c];
c++;
}
if (pixel < pMin)▼
pMin = pixel;▼
▲ pMax = pixel;
}
▲ if (pixel < pMin) pMin = pixel;
foreach (m; khalf .. nx - khalf)▼
}
▲ }
▲ }
▲ foreach (m; khalf .. nx - khalf) {
foreach (n; khalf .. ny - khalf) {
float pixel = 0.0;
int c;
foreach (j; -khalf .. khalf + 1) {
foreach (i; -khalf .. khalf + 1) {
pixel += inp[(n - j) * nx + m - i] * kernel[c];
c++;
}
static if (
pixel = MAX_BRIGHTNESS * (pixel - pMin) / (pMax - pMin);
outp[n * nx + m] = cast(Pixel)pixel;
}
▲ }
}
Line 589 ⟶ 586:
kernelSize = 2 * int(2*sigma) + 3;
*/
void gaussianFilter
/*enum*/ immutable float mean = cast(float)floor(n / 2.0);
auto kernel = new float[n * n]
debug fprintf(stderr,
"gaussianFilter: kernel size %d, sigma=%g\n",
n, sigma);
int c;
foreach (i; 0 .. n) {
foreach (j; 0 .. n) {
kernel[c] = exp(-0.5 * (pow((i - mean) / sigma, 2.0) +
Line 606 ⟶ 604:
c++;
}
▲ }
convolution(inp, outp, kernel[], nx, ny, n, true);▼
}
Line 619:
tMin, and tMax are lower and upper thresholds.
*/
Pixel[] cannyEdgeDetection
nothrow {
immutable int nx = header.width;
immutable int ny = header.height;
auto outp = new Pixel[header.bmp_bytesz];
auto G = new Pixel[nx * ny];▼
auto after_Gx = new Pixel[nx * ny];▼
gaussianFilter
__gshared immutable float[] Gx = [-1, 0, 1,
Line 641 ⟶ 637:
-1,-2,-1];
convolution!(false)(outp, after_Gx, Gx, nx, ny, 3);
convolution!(false)(outp, after_Gy, Gy, nx, ny, 3);
▲ auto G = new Pixel[nx * ny];
foreach (i; 1 .. nx - 1)
foreach (j; 1 .. ny - 1) {
immutable int c = i + nx * j;
G[c] = cast(Pixel)hypot(after_Gx[c], after_Gy[c]);
▲ if (G[c] > Gmax)
}
// Non-maximum suppression, straightforward implementation.
foreach (i; 1 .. nx - 1)
foreach (j; 1 .. ny - 1) {
Line 702 ⟶ 700:
immutable int t = edges[nedges];
int[8]
foreach (k; 0 .. 8)
if (nms[
outp[
edges[nedges] = neighbours[k];
nedges++;
}
Line 728 ⟶ 727:
if (args.length < 2) {
printf("Usage: %s image.bmp\n", (args[0] ~ "\0").ptr);
return
}
const inputBitmap_ih = loadBMP(args[1]);
const inputBitmap = inputBitmap_ih[0];
▲ return 1;
printf("Info: %d x %d x %d\n", ih.width, ih.height, ih.bitspp);
ih, 45, 50, 1.0f));
▲ const outputBitmap = cannyEdgeDetection!(1.0f)(inputBitmap,
▲ ih, 45, 50);
}</lang>
|