# Detect and correct sheared squares in image

I have the image

I want to detect the plots and warp them into perfect squares. My workflow so far:

corners=ImageCorners[img,10];


This returns a lot of corners, and I find I have to go through them manually. I would really appreciate a heuristic to find the proper corners automatically, maybe some filter based on the amount of whitespace in a big (50 px) smoothed area around a pixel. To manually select corners:

HighlightImage[img,MapIndexed[Labeled[#1,ToString@First@#2]&,corners[[;;200]]]]
(*no good way to layout that many labels,
is there a way to dynamically make the labels near the mouse pointer big?*)
HighlightImage[img,MapIndexed[Labeled[#1,ToString@First@#2]&,
corners[[Join[{15,171,89,108},{77,113,79,158}]]]]]


I don't know if those indices will be the same on every machine. Finally, the warping

sketch0=ImageTake[ImageTransformation[img,Last@FindGeometricTransform[
corners[[{15,171,89,108}]],{20,20}+#&/@{{0,#},{0,0},{#,0},{#,#}}&@300],
ImageDimensions@img,DataRange->Full],All,{0,340}]
sketch1=ImageTake[ImageTransformation[img,Last@FindGeometricTransform[
corners[[{77,113,79,158}]],{20,20}+#&/@{{0,#},{0,0},{#,0},{#,#}}&@300],
ImageDimensions@img,DataRange->Full],All,{0,340}]


I'm not super concerned about the dewarping code. It's ugly, but does the trick.

Feedback on my code is appreciated, as well as less tedious methods for detecting features. In my mind a perfect program to do this would highlight the closest strong corner to the mouse as it moves across the image so you could quickly select the relevant features -- a module like this is feasible in Mathematica.

Feedback on my code is appreciated, as well as less tedious methods for detecting features. In my mind a perfect program to do this would highlight the closest strong corner to the mouse as it moves across the image so you could quickly select the relevant features -- a module like this is feasible in Mathematica.

If I understood, maybe this will help for a manual but quicker method of identifying the corners.

You can use the image edit Coordinate tool , and copy as a list

I actually think your attempt is really nice, I'm not sure you'll get it any more 'square'.

Maybe trying to recreate the data within the square and plotting could be interesting

With the same method:

You can start to rebuild by taking the coordinates and indices

or follow the methods to recreate in this post

• Thanks! I have since used the imprecise method of coordinate selection to process other images. I suppose the optimal UI would involve a way to snap the mouse to (code specified) maxima... might do a self-answer with this idea.
Aug 15, 2021 at 6:55
• Nice! Could be interesting, I used a similar method to remove wrongly identified ROIs. If you haven't encountered them, Dynamic[MousePosition[]] & ClickPane[] could be helpful. GL Aug 15, 2021 at 18:39

To extract well separated sub images from a composite image, we can proceed as follows:

I assume that the sub images are arrange horizontally with a clear gap, like e.g.:

We first make the image into black and white without gray. Then we transform it into an array of 0 and 1 (0 corresponds to black, 1 to white):

im = ImageAdjust[im0];
im = Binarize[im, .9];
xy = MorphologicalComponents[im];


Next, we determine the positions of the zeros. Then we determine the horizontal positions of the pixels without duplicates (note the graphics coordinates x/y are the array coordinates y/x ).

pos = Position[xy, 0];
posx = Union@pos[[All, 2]];


As the partial images are well separated along the horizontal axes, we can split the x positions into continuous pieces:

posx = MinMax /@ Split[posx, #2 - #1 < 5 &];


Next, we determine the min/max y coordinates of the different x- pieces:

sely[int_] :=
MinMax[Select[pos, IntervalMemberQ[Interval[int], #[[2]]] &][[All, 1]]];
posy = sely /@ posx;


We now have the extremal x/y coordinates of the sub images and can extract these sub images:

images=(OperatorApplied[ImageTake, 3][im0]) @@@ Transpose[{posy, posx}]


• A very slick way to sort of crop the images, but I'm interested in scaling and rotating to become squares. Detecting the corners is key (for example in the case that all edges bulge and the extrema aren't useful coordinates).