参考:
https://blog.youkuaiyun.com/qq_35054151/article/details/88952728
注意:
这个可能不是最大内接矩形。
输入图像 :
输出图像:
代码:
public void Main()
{
Mat src = Cv2.ImRead(FilePath.Image.Shapes, ImreadModes.AnyColor);
Mat gray = new Mat();
Mat binary = new Mat();
Cv2.CvtColor(src, gray, ColorConversionCodes.RGB2GRAY);
Cv2.Threshold(gray, binary, 10, 255, ThresholdTypes.Binary);
ConnectedComponents cc = Cv2.ConnectedComponentsEx(binary);
foreach (var maxBlob in cc.Blobs.Skip(1))
{
Mat m = new Mat(binary, maxBlob.Rect);
Rect rr = InSquare(m, new Point(m.Width / 2, m.Height / 2));
Cv2.Rectangle(src, new Rect(maxBlob.Left + rr.Left, maxBlob.Top + rr.Top, rr.Width, rr.Height), Scalar.Red);
}
}
/// <summary>
/// 内接矩形
/// </summary>
/// <param name="img"></param>
/// <param name="center"></param>
/// <returns></returns>
Rect InSquare(Mat img, Point center)
{
int[] edge = new int[4];
edge[0] = center.Y - 1;//top
edge[1] = center.X + 1;//right
edge[2] = center.Y + 1;//bottom
edge[3] = center.X - 1;//left
bool[] EXPAND = { true, true, true, true };
int n = 0;
while (EXPAND[0] || EXPAND[1] || EXPAND[2] || EXPAND[3])
{
int edgeID = n % 4;
EXPAND[edgeID] = ExpandEdge(img, edge, edgeID, EXPAND);
n++;
}
Point tl = new Point(edge[3], edge[0]);
Point br = new Point(edge[1], edge[2]);
return new Rect(tl, new Size(br.X - tl.X, br.Y - tl.Y));
}
/// <summary>
/// 扩展边界函数
/// </summary>
/// <param name="img"></param>
/// <param name="edge">边界数组,存放4条边界值</param>
/// <param name="edgeID">当前边界号</param>
/// <returns>确定当前边界是否可以扩展</returns>
bool ExpandEdge(Mat img, int[] edge, int edgeID, bool[] EXPAND)
{
int width = img.Width;
int height = img.Height;
switch (edgeID)
{
//top
case 0:
if (!EXPAND[0]) return false;
if (edge[0] <= 1)
return false;
for (int i = edge[3] + 1; i < edge[1]; ++i) // left - right
{
if (img.Get<byte>(edge[0], i) == 0)
{
Console.WriteLine("top");
return false;
}
else
img.Set<byte>(edge[0], i, 100);
}
edge[0]--;
return true;
//right
case 1:
if (!EXPAND[1]) return false;
if (edge[1] >= width)
return false;
for (int i = edge[0] + 1; i < edge[2]; ++i) // top - bottom
{
if (img.Get<byte>(i, edge[1]) == 0)
{
Console.WriteLine("right");
return false;
}
else
img.Set<byte>(i, edge[1], 50);
}
edge[1]++;
return true;
//botton
case 2:
if (!EXPAND[2]) return false;
if (edge[2] >= height)
return false;
for (int i = edge[3] + 1; i < edge[1]; ++i) // left - right
{
if (img.Get<byte>(edge[2], i) == 0)
{
Console.WriteLine("botton");
return false;
}
else
img.Set<byte>(edge[2], i, 100);
}
edge[2]++;
return true;
//left
case 3:
if (!EXPAND[3]) return false;
if (edge[3] < 1)
return false;
for (int i = edge[0] + 1; i < edge[2]; ++i) // top - bottom
{
if (img.Get<byte>(i, edge[3]) == 0)
{
Console.WriteLine("left");
return false;
}
else
img.Set<byte>(i, edge[3], 50);
}
edge[3]--;
return true;
default:
return false;
}
}