Image editing using ArrayFire

Pradeep Garigipati ArrayFire, Image Processing 2 Comments

In this post, we will be looking at the following simple image editing operations using the ArrayFire library.

  • contrast modification
  • brightness modification
  • translation
  • digital zoom
  • alpha blending
  • unsharp mask

Code required to do each operation and the corresponding input/output sample are given below in their corresponding sections. All the operations are built using some existing image manipulation functions and the awesome element-wise operations in ArrayFire.

Contrast modification

/**
 * contrast value should be in the range [-1,1]
 **/
void changeContrast(array &in, const float contrast)
{
    float scale     = tan((contrast+1)*Pi/4);
    in = ((in/255.0f - 0.5f) * scale + 0.5f) * 255.0f;
}

Brightness modification

/**
 * brightness value should be in the range [0,1]
 **/
void changeBrightness(array &in, const float brightness, const float channelMax=255.0f)
{
    float factor = brightness*channelMax;
    in = (in + factor);
}

You may add an additional step to the above function that clamps each pixel value to [0,255] range. Clamping can be easily achieved by the following line of code.

image = (image<0.0f)*0.0f + (image>255.0f)*255.0f + (image>=0.0f && image<=255.0f)*image;

or a more generalized clamp/thresholding operation would like as below.

array clamp(const array &in, float min=0.0f, float max=255.0f)
{
    return ((inmax)*255.0f + (in>=min && in <=max)*in);
}

Image translation

This operation can be achieved directly by a function in our library translate. A sample output of the function translate(a,100,100,200,126) on the sample input is provided below.

Digital Zoom

array digZoom(const array &in, int x, int y, int width, int height)
{
    array cropped = in(seq(height)+x,seq(width)+y,span);
    return resize((unsigned)in.dims(0),(unsigned)in.dims(1),cropped);
}

Alpha Blending

array alphaBlend(const array &foreground, const array &background, const array &mask)
{
    array tiledMask;
    if (mask.dims(2)!=foreground.dims(2))
        tiledMask = tile(mask,1,1,foreground.dims(2));
    return foreground*tiledMask+(1.0f-tiledMask)*background;
}

For the purpose of this example, a very simple mask was created using the following code stub.

array intensity = colorspace(fight,af_gray,af_rgb);
array mask = clamp(intensity,10.0f,255.0f)>0.0f;

A more detailed and accurate mask would deliver more appropriate blending.

Unsharpmask

/**
 * radius effects the level of details that will effected during sharpening process
 * amount value should be in the range [0,1] or [1,]
 * note: value of 1.0 for amount results unsharp masking
 *       values > 1.0 results in highboost filter effect
 **/
array usm(const array &in, float radius, float amount)
{
    int gKernelLen  = 2*radius + 1;
    array blurKernel= gaussiankernel(gKernelLen,gKernelLen);
    array blur  = convolve(in,blurKernel);
    return (in + amount*(in - blur));
}

Conclusion

We are working on a free image editing application based on ArrayFire. This is the first part of the series that discusses our progress. You can follow the project here.

Comments 2

  1. Pingback: Image editing using ArrayFire: Part 2 | ArrayFire

  2. Pingback: Image editing using ArrayFire: Part 3 | ArrayFire

Leave a Reply

Your email address will not be published.