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
Pingback: Image editing using ArrayFire: Part 2 | ArrayFire
Pingback: Image editing using ArrayFire: Part 3 | ArrayFire