На данный момент мы предположим, что все они должны быть прямоугольниками без вращения. В этом случае вы должны быть в состоянии использовать довольно простой подход. Начиная с каждого пикселя на краю растрового изображения, начинайте сэмплирование пикселей, проходящих внутрь, пока не встретите переход. Запишите расстояние от края для каждого перехода (если он есть). После того как вы сделали это с каждого края, вы в основном «голосуете» - расстояние, которое чаще всего происходило от этого края, - это то, что вы рассматриваете как этот край прямоугольника. Если прямоугольник действительно выровнен, это должно составлять большую часть расстояний.
Если вместо этого вы видите несколько расстояний с почти одинаковыми частотами, есть вероятность, что прямоугольник повернут (или, по крайней мере, один край). В этом случае вы можете разделить сторону пополам (например) и повторить. Как только вы достигли подавляющего большинства точек в каждом регионе, согласовав расстояние, вы можете (попытаться) линейно интерполировать между ними, чтобы получить прямую линию (и ограничение минимального размера региона ограничит максимальное вращение - если вы получите до некоторого размера, не достигнув соглашения, вы смотрите на борозду, а не на край прямоугольника). Аналогично, если у вас есть регион (или более одного), который не совсем совпадает с остальными и не будет соответствовать линии, вам, вероятно, следует также игнорировать его - опять же, вы, вероятно, смотрите на выбоину не то, что задумано как ребро.