# Detecting line crossings on an image

I want to detect line crossings, especially in the supplied example images the crossings at edges of pavement for feature tracking. I specifically want to avoid tracking other kinds of features in the image, and a method that would emphasise likely line crossings and de-emphasise other features would be welcome. I've tried various combinations of ImageCorrelate, ImageConvolve, EdgeDetect, etc., with custom or stock kernels, failing to get results of any usefulness. Edge detection doesn't have too much trouble detecting lines, but I'm interested of crossings!

Example photos are below.

• For these pictures, I presume you don't want to have to manually mask out anything that isn't the ground? May 24, 2020 at 11:23
• @J.M. Yes, I hope manual masking is not necessary. At the same time, both false positives and false negatives are tolerable as long as most of the detected crossings on these sort of images would consist of corners of these tiles. May 24, 2020 at 11:27
• Have you tried using ImageLines? May 24, 2020 at 13:52
• @RohitNamjoshi I considered it, but I'm more interested about detecting crossings on basis of local image neighbourhoods. May 24, 2020 at 14:21
• If you're okay with manually drawing a quad around the pavement, you could apply an inverse perspective transform first to get the pavement into a squareish image which is easier to crop. Then this will improve the crossing detection later. May 24, 2020 at 14:24

My first crude idea to get the computer to handle the masking is to chop the first image up into chunks and use Classify to learn what chunks are pavement vs. building. You can crop out these regions using ImageTake without much effort.

img = Import["https://i.stack.imgur.com/91qUZ.jpg"];
chunksize = 16;
pavementParts =
Flatten[ImagePartition[ImageTake[img, {1450, -1}, {700, 2000}],
chunksize], 1];
buildingsParts =
Flatten[ImagePartition[ImageTake[img, {0, 1100}, {0, 1100}],
chunksize], 1];
ceilingParts =
Flatten[ImagePartition[ImageTake[img, {0, 700}, {600, 2600}],
chunksize], 1];


Then train the classifier:

trainingData =
Join[(# -> 0) & /@ buildingsParts, (# -> 0) & /@
ceilingParts, (# -> 1) & /@ pavementParts];
cf = Classify[trainingData];


Then classify the image chunks, replacing them with all-white or all-black chunks depending on the result. We use Dilation to fill in any holes in the resulting mask.

whitechunk = Image@ConstantArray[0, {chunksize, chunksize}];
blackchunk = Image@ConstantArray[1, {chunksize, chunksize}];
parts = ImagePartition[img, chunksize];
cfresult =
ImageAssemble[
ParallelMap[cf, parts, {2}] /. {1 -> blackchunk, 0 -> whitechunk}];


Finally, apply a CornerFilter and multiply the result by the mask.

keyp = ImageMultiply[Binarize[CornerFilter[img, 3]], mask] //
ImageKeypoints;
Show[img, Graphics[{Red, Point[keyp]}]]


If you want to EdgeDetect or CrossingDetect you don't need the keypoints. Apply these first before ImageMultiply-ing by the mask.

The result is not fantastic, but you can use the classifier to pick out parts of the pavement in the second image (and unfortunately some buildings got in there too):

img2 = Import["https://i.stack.imgur.com/U1esM.jpg"];
img2parts = ImagePartition[img2, chunksize];
cfresult2 =
ImageAssemble[
ParallelMap[cf, img2parts, {2}] /. {1 -> blackchunk,
0 -> whitechunk}];