I am new to image processing and am working with images like these:
In these pictures, there will be more than one curves that I need to straighten out for them to look like a straight line.
Here's a quick solution. It can be improved by doing a spline fit to the features rather than just fitting the parabola. The algorithm shifts each row in the image individually according to the fitted parabola:
from skimage import io, measure, morphology
from matplotlib import pyplot as plt
from scipy.optimize import curve_fit
image = io.imread('curves.png', as_gray=True)
# need a binary mask of features
mask = image == image.min()
# close holes in features
mask = morphology.binary_closing(mask, morphology.square(3))
plt.matshow(mask, cmap='gray')
# need to get the coordinates of each feature
rp = measure.regionprops(measure.label(mask))
# going to fit a parabola to the features
def parabola(x, x0, A, y0):
return A*(x-x0)**2 + y0
# get coords of one of the features
coords = rp[0].coords
# do parabola fit
pop, pcov = curve_fit(parabola, coords[:,0], coords[:,1])
# generate fit
fit = parabola(np.arange(mask.shape[0]), *pop)
# plot fit
plt.plot(fit, np.arange(mask.shape[0])) # invert axes
# generate new image to shift
out = np.empty_like(image)
# shift each row individually and add to out array
for i, row in enumerate(image):
out[i] = np.roll(row, -int(round(fit[i] - pop[-1])))
plt.matshow(out, cmap='gray')
Original mask and fitted parabola:
Result: