最大内接矩形,从轮廓中所有坐标中获取其中4个坐标即可:
python 获取过程如下:
def order_points(pts):
# pts为轮廓坐标
# 列表中存储元素分别为左上角,右上角,右下角和左下角
rect = np.zeros((4, 2), dtype = "float32")
# 左上角的点具有最小的和,而右下角的点具有最大的和
s = pts.sum(axis = 1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
# 计算点之间的差值
# 右上角的点具有最小的差值,
# 左下角的点具有最大的差值
diff = np.diff(pts, axis = 1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
# 返回排序坐标(依次为左上右上右下左下)
return rect
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.blur(gray, (9, 9))
_, thresh = cv2.threshold(blurred, 155, 255, cv2.THRESH_BINARY)
_, cnts, _ = cv2.findContours( thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]<br>先找出轮廓点
rect = order_points(c.reshape(c.shape[0], 2))
print(rect)
xs = [i[0] for i in rect]
ys = [i[1] for i in rect]
xs.sort()
ys.sort()
#内接矩形的坐标为
print(xs[1],xs[2],ys[1],ys[2])
c++版
OpenCVSharp 小练习 最大内接矩形_tfarcraw的博客-CSDN博客
opencv:求区域的内接矩形_cfqcfqcfqcfqcfq的博客-CSDN博客_opencv 内接矩形
#include<opencv2\opencv.hpp>
#include <iostream>
#include<vector>
using namespace cv;
using namespace std;
/**
* @brief expandEdge 扩展边界函数
* @param img:输入图像,单通道二值图,深度为8
* @param edge 边界数组,存放4条边界值
* @param edgeID 当前边界号
* @return 布尔值 确定当前边界是否可以扩展
*/
bool expandEdge(const Mat & img, int edge[], const int edgeID)
{
//[1] --初始化参数
int nc = img.cols;
int nr = img.rows;
switch (edgeID) {
case 0:
if (edge[0]>nr)
return false;
for (int i = edge[3]; i <= edge[1]; ++i)
{
if (img.at<uchar>(edge[0], i) == 255)//遇见255像素表明碰到边缘线
return false;
}
edge[0]++;
return true;
break;
case 1:
if (edge[1]>nc)
return false;
for (int i = edge[2]; i <= edge[0]; ++i)
{
if (img.at<uchar>(i, edge[1]) == 255)//遇见255像素表明碰到边缘线
return false;
}
edge[1]++;
return true;
break;
case 2:
if (edge[2]<0)
return false;
for (int i = edge[3]; i <= edge[1]; ++i)
{
if (img.at<uchar>(edge[2], i) == 255)//遇见255像素表明碰到边缘线
return false;
}
edge[2]--;
return true;
break;
case 3:
if (edge[3]<0)
return false;
for (int i = edge[2]; i <= edge[0]; ++i)
{
if (img.at<uchar>(i, edge[3]) == 255)//遇见255像素表明碰到边缘线
return false;
}
edge[3]--;
return true;
break;
default:
return false;
break;
}
}
/**
* @brief 求取连通区域内接矩
* @param img:输入图像,单通道二值图,深度为8
* @param center:最小外接矩的中心
* @return 最大内接矩形
* 基于中心扩展算法
*/
cv::Rect InSquare(Mat &img, const Point center)
{
// --[1]参数检测
if (img.empty() ||img.channels()>1|| img.depth()>8)
return Rect();
// --[2] 初始化变量
int edge[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
//[2]
// --[3]边界扩展(中心扩散法)
bool EXPAND[4] = { 1,1,1,1 };//扩展标记位
int n = 0;
while (EXPAND[0] || EXPAND[1] || EXPAND[2] || EXPAND[3])
{
int edgeID = n % 4;
EXPAND[edgeID] = expandEdge(img, edge, edgeID);
n++;
}
//[3]
//qDebug() << edge[0] << edge[1] << edge[2] << edge[3];
Point tl = Point(edge[3], edge[0]);
Point br = Point(edge[1], edge[2]);
return Rect(tl, br);
}
int main()
{
bool isExistence = false;
float first_area = 0;
/// 加载源图像
Mat src;
src = imread("cen.bmp", 1);
//src = imread("C:\\Users\\Administrator\\Desktop\\测试图片\\xxx\\20190308152516.jpg",1);
//src = imread("C:\\Users\\Administrator\\Desktop\\测试图片\\xx\\20190308151912.jpg",1);
//src = imread("C:\\Users\\Administrator\\Desktop\\测试图像\\2\\BfImg17(x-247 y--91 z--666)-(492,280).jpg",1);
cvtColor(src, src, CV_RGB2GRAY);
threshold(src, src, 100, 255, THRESH_BINARY);
Rect ccomp;
Point center(src.cols / 2, src.rows / 2);
//floodFill(src, center, Scalar(255, 255, 55), &ccomp, Scalar(20, 20, 20), Scalar(20, 20, 20));
if (src.empty())
{
cout << "fali" << endl;
}
//resize(src, src, cv::Size(496, 460), cv::INTER_LINEAR);
imshow("src", src);
Rect rr = InSquare(src, center);
rectangle(src, rr, Scalar(255), 1, 8);
imshow("src2", src);
waitKey(0);
getchar();
return 0;
}
原图和效果图: