图像练习-矩形4点OpenCV(01)
提取出里面最大矩形的四个顶点坐标
源图像
结果展示
代码
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();
}