![linear image vectorizer linear image vectorizer](https://st.depositphotos.com/50500684/54818/v/380/depositphotos_548182736-stock-illustration-currency-icons-euro-eps-vector.jpg)
![linear image vectorizer linear image vectorizer](http://1.bp.blogspot.com/-XlYDW_OQLoU/T0NjngjOU-I/AAAAAAAAAC4/urtsBDpVU00/s1600/vectormagic.jpg)
X_prev = (x_prev < width_in) ? x_prev : width_in - 1 Sanitize bounds - no need to check for < 0 Nearest neighbours coordinates in input space Corresponding absolute coordinates of the pixel in input spaceĬonst float x_in = x_out * (float)width_in Ĭonst float y_in = y_out * (float)height_in
![linear image vectorizer linear image vectorizer](http://media5.datahacker.rs/2020/03/Picture24-2-1017x1024.jpg)
Relative coordinates of the pixel in output spaceĬonst float x_out = (float)j /(float)width_out Ĭonst float y_out = (float)i /(float)height_out Schedule(simd:static) aligned(in, out:64) \įirstprivate(in, out, width_out, height_out, width_in, height_in, ch) #pragma omp parallel for simd collapse(2) default(none) \ + Dy_next * (array_in * Dx_next + array_in * Dx_prev)Īnd here is the pure C with OpenMP pragmas to vectorize, paralellize and such : static inline void interpolate_bilinear(const float *const restrict in, const size_t width_in, const size_t height_in,įloat *const restrict out, const size_t width_out, const size_t height_out, Dx_next # because next - prev = 1Īrray_out = Dy_prev * (array_in * Dx_next + array_in * Dx_prev) \ Dy_next # because next - prev = 1ĭx_prev = 1.
![linear image vectorizer linear image vectorizer](http://rel.phatcode.net/mytutes/3dtutes/chapter3/Chapter3_files/VectorProjection.gif)
# Distances between neighbour nodes in input spaceĭy_prev = 1. # Sanitize bounds - no need to check for < 0 # Nearest neighbours coordinates in input space # Corresponding absolute coordinates of the pixel in input space # Relative coordinates of the pixel in output space Okay, okay, here is the Python : import numpy as npĭef interpolate_bilinear(array_in, width_in, height_in, array_out, width_out, height_out): This will not show up in every image you will process, but it’s not because you don’t see it that it doesn’t happen. So, again, in the spirit of working cleanly, let’s work with OETF off. Which implies working in float because uint8 without OETF will fail. So, we need a good (and fast) way to interpolate float RGB images. Among all the interpolation methods, the bilinear is the most efficient of the ok-ish. It won’t give you the precision of a Lanczos 3, but it’s good for low-level image manipulation like guided filters and such. You see here that the image rotated without OETF (undo the “gamma”, apply the linear map, redo the “gamma” and save) doesn’t have the dark fringe of the one rotated with the OETF on (apply the linear map and save). PIL supports floating point interpolation, but only for one layer, thus forget about RGB, and is deprecated and soon to be removed. The drawback of uint8 is it cannot store negative values, which is important if you are doing wavelets-style frequency separation. Of course, there are tricks like adding 127 and normalizing, but tricks are bad in general, and the floating point arithmetic capabilities of modern CPU make any integer arithmetic speed-up unworthy of the rounding. Let’s be clean from ground up. The other drawback, that people often forget, is working in uint8 always assumes that your pixels are non-linearly encoded with an OETF ( Opto-electrical transfer function), improperly called a gamma, that is meant to alleviate quantization errors in lower bits (hence lower lights), which produce banding in smooth gradients in low lights. But performing convolutions, thus interpolations and linear maps, on OETF-encoded imagery does not retain the physical consistency of the pixel garbage with the scene light emission and will mess up gradients, possibly giving edge-artifacts : This is quite annoying if you are working with floating point images. If you are working in image processing and using Python as a prototyping script language to test algorithms, you might have noticed that all the libs providing fast image interpolation methods (to either sub-sample or over-sample) work in 8 bits unsigned integers ( uint8).