提取出里面最大矩形的四个顶点坐标
源图像
结果展示
代码
void getLine(std::vector<int>& data, int threshold)
{
for (int x = 0; x < data.size(); x++)
{
if (0 == data[x])
{
continue;
}
int maxValue = 0, maxLoc = -1, i = -1;
for (i = x; i < data.size(); ++i)
{
if (data[i] > maxValue)
{
maxValue = data[i];
maxLoc = i;
}
if (data[i] == 0)
{
break;
}
data[i] = 0;
}
x = i;
data[maxLoc] = 1;
}
}
void rectangle_vertex_old()
{
cv::Mat image = cv::imread("rectangle_vertex.jpg", cv::IMREAD_COLOR);
cv::Mat gray;
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
cv::Mat binary = gray < 100;
//计算x及y方向投影
std::vector<int> widthHist(binary.cols, -1);
std::vector<int> heightHist(binary.rows, -1);
for (int y = 0; y < binary.rows; y++)
{
for (int x = 0; x < binary.cols; x++)
{
int value = (int)binary.at<uchar>(y, x) / 255.0;
heightHist[y] = heightHist[y] + value;
widthHist[x] = widthHist[x] + value;
}
}
int histThreshold = (int)(binary.rows * 0.7);
//y方向的投影二值化
for (int y = 0; y < binary.rows; y++)
{
if (heightHist[y] < histThreshold)
{
heightHist[y] = 0;
}
}
//计算水平线的位置
getLine(heightHist, histThreshold);
histThreshold = (int)(binary.cols * 0.7);
//x方向的投影二值化
for (int y = 0; y < binary.cols; y++)
{
if (widthHist[y] < histThreshold)
{
widthHist[y] = 0;
}
}
//计算垂直线的位置
getLine(widthHist, histThreshold);
//寻找左上点左下点
cv::Point ptLeftTop(-1, -1), ptLeftDown(-1, -1);
for (int x = 0; x < binary.cols; x++)
{
if (widthHist[x] == 1)
{
for (int y = 0; y < binary.rows; y++)
{
if (heightHist[y] == 1)
{
ptLeftTop.x = x;
ptLeftTop.y = y;
}
}
for (int y = binary.rows - 1; y > 0; y--)
{
if (heightHist[y] == 1)
{
ptLeftDown.x = x;
ptLeftDown.y = y;
}
}
break;
}
}
//寻找右上点右下点
cv::Point ptRightTop(-1, -1), ptRightDown(-1, -1);
for (int x = binary.cols - 1; x > 0; x--)
{
if (widthHist[x] == 1)
{
for (int y = 0; y < binary.rows; y++)
{
if (heightHist[y] == 1)
{
ptRightTop.x = x;
ptRightTop.y = y;
}
}
for (int y = binary.rows - 1; y > 0; y--)
{
if (heightHist[y] == 1)
{
ptRightDown.x = x;
ptRightDown.y = y;
}
}
break;
}
}
//画出4个点
if (ptLeftTop != cv::Point(-1, -1))
{
cv::circle(image, ptLeftTop, 4, cv::Scalar(0, 0, 255, 0), 4);
}
if (ptLeftDown != cv::Point(-1, -1))
{
cv::circle(image, ptLeftDown, 4, cv::Scalar(0, 0, 255, 0), 4);
}
if (ptRightTop != cv::Point(-1, -1))
{
cv::circle(image, ptRightTop, 4, cv::Scalar(0, 0, 255, 0), 4);
}
if (ptRightDown != cv::Point(-1, -1))
{
cv::circle(image, ptRightDown, 4, cv::Scalar(0, 0, 255, 0), 4);
}
cv::namedWindow("src_old");
cv::imshow("src_old", image);
cv::waitKey();
}