• 图像练习-答题卡opencv(02)


    原图 

     结果
    代码 
    1. // Load source image
    2. cv::Mat src = cv::imread("answer_card.jpg", cv::IMREAD_COLOR);
    3. if (src.empty())
    4. {
    5. return;
    6. }
    7. cv::Mat gray;
    8. cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
    9. cv::Mat binary;
    10. double value = cv::threshold(gray, binary, 0, 255, cv::THRESH_BINARY_INV + cv::THRESH_OTSU);
    11. std::vector imgCorners{ cv::Point2f(0, 0), cv::Point2f(src.cols, 0),
    12. cv::Point2f(src.cols, src.rows), cv::Point2f(0, src.rows) };
    13. cv::Mat dilate;
    14. cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1, 7));
    15. cv::dilate(binary, dilate, kernel);
    16. std::vector> contours;
    17. cv::findContours(dilate, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
    18. std::vector corners;
    19. for (size_t i = 0; i < contours.size(); i++)
    20. {
    21. cv::RotatedRect minRect = cv::minAreaRect(contours[i]);
    22. // rotated rectangle
    23. cv::Point2f sz[4];
    24. minRect.points(sz);
    25. if (cv::Rect(minRect.boundingRect()).width > src.cols / 2) // should be improved
    26. {
    27. for (int j = 0; j < 4; ++j) //找到与图像四点最近的对应四点
    28. {
    29. cv::Point2f pt = imgCorners[j];
    30. cv::Point2f nearest_pt = sz[0];
    31. float dist = cv::norm(pt - nearest_pt); //求两点的距离
    32. for (int k = 1; k < 4; ++k)
    33. {
    34. if (cv::norm(pt - sz[k]) < dist)
    35. {
    36. dist = cv::norm(pt - sz[k]); //更新两点距离
    37. nearest_pt = sz[k];
    38. }
    39. }
    40. corners.push_back(nearest_pt);
    41. }
    42. }
    43. }
    44. //提取涂抹的黑色小圆
    45. cv::Mat erode0;
    46. cv::erode(binary, erode0, cv::Mat(), cv::Point(-1, -1), 10); //should be improved
    47. cv::Mat dilat;
    48. cv::dilate(erode0, dilat, cv::Mat(), cv::Point(-1, -1), 5); //should be improved
    49. cv::Mat results(src.size(), CV_8UC3);
    50. cv::Mat transform = cv::getPerspectiveTransform(corners, imgCorners);
    51. cv::warpPerspective(src, results, transform, src.size()); // Create a Mat To Show results
    52. cv::Mat warp(src.size(), CV_8UC1); // should be improved
    53. cv::warpPerspective(dilat, warp, transform, src.size());
    54. //试卷答题卡选项数目
    55. cv::Size size(20, 5); // this variable should be changed according input
    56. cv::Mat resize;
    57. cv::resize(warp, resize, size);
    58. for (int i = 0; i < resize.cols; ++i)
    59. {
    60. std::string answer = "";
    61. answer += resize.at(1, i) == 0 ? "" : "A";
    62. answer += resize.at(2, i) == 0 ? "" : "B";
    63. answer += resize.at(3, i) == 0 ? "" : "C";
    64. answer += resize.at(4, i) == 0 ? "" : "D";
    65. if (answer.length() > 1) answer = "X"; // Double mark
    66. int y = 0;
    67. if (answer == "A") y = results.rows / size.height;
    68. if (answer == "B") y = results.rows / size.height * 2;
    69. if (answer == "C") y = results.rows / size.height * 3;
    70. if (answer == "D") y = results.rows / size.height * 4;
    71. if (answer == "") answer = "[-]";
    72. cv::putText(results, answer, cv::Point(50 * i + 15, 30 + y), cv::FONT_HERSHEY_PLAIN, 2, CV_RGB(0, 0, 255), 2);
    73. }
    74. imshow("results", results);
    75. cv::waitKey();

  • 相关阅读:
    重学Elasticsearch第1章 : Elasticsearch, Kibana概念、Elasticsearch相关术语
    Python调用企微机器人: 发送常用格式汇总
    我和谷歌共成长-资深安卓开发的转型之路
    通过大型语言模型 (LLM)降低运营成本
    无需编程经验,也能制作租车预约微信小程序,快速上手
    23 Python的shutil模块
    dubbo-admin 的安装
    MySQL 清空分区表单个分区数据
    数据结构-难点突破(C++/Java详解实现串匹配算法KMP,next数组求法,KMP算法优化nextval数组)
    【Node入门系列】前后端的身份认证 — JWT(10)
  • 原文地址:https://blog.csdn.net/qq_30460949/article/details/133178799