CLIP - Additional Examples

 

The map operator that applies a function to all pixels of an image can also accept the coordinate of the pixel. For example, the following program reads a color image, and then inverts the image except a circle with radius of 128 located at the center of the image:


  1. 1.#include "pnm_env.h"

  2. 2.

  3. 3.fRgbPix disk(int x, int y, fRgbPix p)

  4. 4.{

  5. 5.   static fRgbPix whitePix(255,255,255);

  6. 6.

  7. 7.   if (x*x+y*y < 128*128) return p;

  8. 8.   return whitePix - p;

  9. 9.}

  10. 10.

  11. 11.int main()

  12. 12.{

  13. 13.    fRgbImg img = pnm(stdin);

  14. 14.    img.SetOrigin(img.GetWidth()/2,img.GetHeight()/2);

  15. 15.    pnm((bRgbImg) img.map(disk)).Write(stdout);

  16. 16.}


  [PREV]                                   [NEXT]

Next is an implementation of the Sobel Edge Detector. The operator work on color images (each channel separately), and trims the results to avoid overflows. The operator is applies using separable kernel components.


  1. 1.#include "pnm_env.h"

  2. 2.

  3. 3.const float g3[3] = { 1.0F,   2.0F1.0F};

  4. 4.const float d3[3] = {-1.0F,   0.0F1.0F};

  5. 5.

  6. 6.fKernel gx3(3,1,g3);

  7. 7.fKernel gy3(1,3,g3);

  8. 8.

  9. 9.fKernel dx3(3,1,d3);

  10. 10.fKernel dy3(1,3,d3);

  11. 11.

  12. 12.

  13. 13.fRgbPix sqrtPix(fRgbPix p)

  14. 14.{

  15. 15.    return fRgbPix(sqrtf(p[0]), sqrtf(p[1]), sqrtf(p[2]));

  16. 16.}

  17. 17.

  18. 18.fRgbPix trim(fRgbPix p)

  19. 19.{

  20. 20.    return fRgbPix (p[0] < 0 ? 0 : (p[0] > 255 ? 255 : p[0]),

  21. 21.                    p[1] < 0 ? 0 : (p[1] > 255 ? 255 : p[1]),

  22. 22.                    p[2] < 0 ? 0 : (p[2] > 255 ? 255 : p[2]));

  23. 23.}

  24. 24.

  25. 25.int main()

  26. 26.{

  27. 27.    fRgbImg img = pnm(stdin);

  28. 28.

  29. 29.    fRgbImg Ix  = (img * gy3) * dx3;

  30. 30.    fRgbImg Iy  = (img * dy3) * gx3;

  31. 31.    fRgbImg res = (Ix*Ix + Iy*Iy).map(sqrtPix);

  32. 32.

  33. 33.    pnm((bRgbImg) res.map(trim)).Write(stdout);

  34. 34.

  35. 35.    return 0;

  36. 36.}

Line (13) reads a color image.

Line (14) sets the origin of the image to center of the image.

Line (15) applies the function disk to the image, convert it to byte and send it to the standard output.


This example also shows some of the limitations of CLIP:

  1. This example does not require floating point data. However, the byte image types serve mostly for I/O and lack many image operators.

  2. The mapped function “disk” has only local pixel information - pixel value and coordinate. It does not have any other image attributes such as dimensions. This is intentional (cleaner definition), but it has its limitations.

Lines (3,4)     define the data used for the separable convolution kernels.

Lines (6-10)   define the convolution kernels for smoothing and derivation in x and y directions.

Lines (12-26) defines map filter for color pixel square root.

Lines (18-23) defines map filter to trim color pixel values to 0..255 range.

Line (27)        reads a color image from the standard input.

Lines (29-31) implements the Sobel operator. The multiplication operator ‘*’ for (image * kernel) or (kernel * kernel) is a convolution operator, and for (image * image) is a pixel by pixel multiplication. The parentheses explicitly apply separable kernel operations.  

Line (33) trims the results to 0..255 range and send it to the standard output.



In this example we defined the smoothing and derivation kernel; however, CLIP has built-in operators for smoothing and derivation, where img.g{x,y)({3,5,7})  are normalized 1D Gaussian smoothing kernels for x and y directions of width 3,5,7 and img.d{x,y)({3,5,7}) are derivation kernels.


The normalized Sobel operator can therefore be defined as:


  1. 1.fRgbImg Ix  = img.gy(3).dx(3);

  2. 2.fRgbImg Iy  = img.dy(3).gx(3);

  3. 3.fRgbImg res = (Ix*Ix + Iy*Iy).map(sqrtPix);