# Detecting rectangle shape from an image

Motivation: I want to automate the process of analyzing "Electron SpectroMeter (ESM)" data. ESM uses magnets to bend electrons so that electrons with different energy are separated spatially. ESM detect electrons by "Imaging plate" which is like a Photograph film which detects electrons instead of lights. images below are ESM data.   Black belts in center of images are where electrons hit on Imaging plate. High energy electrons are on the left side of this belt, and low energy electrons are on the right side. I can get an electron energy spectrum by drawing a line over this belt and taking a line profile. I think I can do this by reading this post : Line Intensity Profile From Image.

But before doing that, I have to choose a starting point and a direction of the line. When I do it manually, I use the "shade" of the magnet. it becomes visible by adjusting contrast of these images. Images adjusted contrast by HistogramTransform are shown in below.   For human's eye, it's clearly detectable that there are rectangle box shape in these images. This rectangle box is the shade of the magnet. I use a middle point of the left edge of the rectangle as a starting point of the line. and draw a line parallel to upper and bottom edges of this rectangle, as shown in the image below. The original question:

I want to do this automatically by Mathematica. The image I want to process contains a rectangle shape and I want get lines which traces over sides of this rectangle.

What I tried:

1. reduce noise by using MedianFilter
2. adjust contrast by using HistogramTransform
3. highlight vertical lines and horizontal lines separately by using EdgeDetect
4. detect lines by ImageLines

The function I made:

DisplayMagnetBox[image_] := Module[
{vlines, hlines, vedge, hedge, mf, ht},
mf = MedianFilter[image, 5];
ht = HistogramTransform[mf];
vlines =
ImageLines[vedge = EdgeDetect[ht, {0, 10}], MaxFeatures -> 6];
hlines =
ImageLines[hedge = EdgeDetect[ht, {10, 0}], MaxFeatures -> 6];
GraphicsRow[
{
Image[mf],
Image[ht],
Image[vedge],
Image[hedge],
Show[HistogramTransform[image],
Graphics[{Thick, Blue, Line /@ Join[vlines, hlines]}]]
},
ImageSize -> 1000
]
] I got a really close result but this function still fails with the first image. I want to process about 30 images like this so I want a better function.

The related questions I found helpful:

If you don't need the rectangle you can easyly find the line for Intensity Profile as you mention.

img=import["http://i.stack.imgur.com/r6cDj.png"];
mf1 = MeanFilter[img, 5];
ht1 = HistogramTransform[mf1];

i = SelectComponents[
SelectComponents[ColorNegate@Binarize[ht1], Small], Large] See this answer here

lineByCenter[center_, semi_, angle_] :=
Rotate[Line[{#1 - #2, #1 + #2}], angle, #1] &[center, {0, semi}]

sa = 1 /. ComponentMeasurements[i, "SemiAxes"]


{113.783, 44.4184}

angle = 1 /. ComponentMeasurements[i, "Orientation"]


-3.14122

bb = Last /@ ComponentMeasurements[i, "BoundingBox"] // First


{{0., 320.}, {235., 410.}}

bbc = Mean /@ bb


{117.5, 365.}

Show[i, Graphics[{Yellow, Opacity [0.5], Rectangle[bb[], bb[]],
Thick, Red, Rotate[Circle[bbc, sa], angle, bbc], Blue,
lineByCenter[bbc, sa[], angle + Pi/2], Green,
lineByCenter[bbc, sa[], angle]}]] 