Как найти контур заполненного варианта ответа в листе ответов?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как найти контур заполненного варианта ответа в листе ответов?

Сообщение Anonymous »

Я хочу найти контур кружка, заполненного карандашом, как на картинке, но findContours() не может работать должным образом. Он всегда находит не тот контур или просто не может его найти.
Картинка, с которой я хочу разобраться:
Изображение

Я попробовал findContours(). Я не знаком с opencv, это был единственный известный мне способ. Я также попробовал HoughCircles, но он тоже не сработал.
Мне нужно решение, чтобы найти счетчик.
Вот это мой код:
void CorrectPerspective(const cv::Mat& InputArray, cv::Mat& OutputArray, const std::vector& InputPoints) {
std::vector xSorted = InputPoints;
std::sort(
xSorted.begin(),
xSorted.end(),
[](const cv::Point2f& a, const cv::Point2f& b) {return a.x < b.x; }
);
std::vector left(xSorted.begin(), xSorted.begin() + 2);
std::vector right(xSorted.begin() + 2, xSorted.end());
std::sort(
left.begin(),
left.end(),
[](const cv::Point2f& a, const cv::Point2f& b) {return a.y < b.y; }
);
cv::Point2f topLeft = left[0];
cv::Point2f bottomLeft = left[1];
std::vector distance;
for (const auto& point : right) {
distance.push_back(cv::norm(topLeft - point));
}
cv::Point2f topRight = right[distance[0] < distance[1] ? 0 : 1];
cv::Point2f bottomRight = right[distance[0] < distance[1] ? 1 : 0];
std::vector sourceVertex = {
topLeft,
topRight,
bottomRight,
bottomLeft
};
float widthA = std::sqrt(std::pow(bottomRight.x - bottomLeft.x, 2) + std::pow(bottomRight.y - bottomLeft.y, 2));
float widthB = std::sqrt(std::pow(topRight.x - topLeft.x, 2) + std::pow(topRight.y - topLeft.y, 2));
int width = static_cast(std::max(widthA, widthB));
float heightA = std::sqrt(std::pow(topRight.x - bottomRight.x, 2) + std::pow(topRight.y - bottomRight.y, 2));
float heightB = std::sqrt(std::pow(topLeft.x - bottomLeft.x, 2) + std::pow(topLeft.y - bottomLeft.y, 2));
int height = static_cast(std::max(heightA, heightB));
std::vector targetVertex = {
cv::Point2f(0, 0),
cv::Point2f(width - 1, 0),
cv::Point2f(width - 1, height - 1),
cv::Point2f(0, height - 1)
};
cv::Mat transformMatrix = cv::getPerspectiveTransform(sourceVertex, targetVertex);
cv::warpPerspective(InputArray, OutputArray, transformMatrix, cv::Size(width, height));
}

void PreProcess(const cv::Mat& InputArray, cv::Mat& OutputArray1, cv::Mat& OutputArray2) {
cv::Mat gray;
cv::cvtColor(
InputArray,
gray,
cv::COLOR_BGR2GRAY
);
cv::Mat gaussianBlurred;
cv::GaussianBlur(
gray,
gaussianBlurred,
cv::Size(5, 5),
0
);
cv::Mat edged;
cv::Canny(
gaussianBlurred,
edged,
50,
200
);
OutputArray1 = edged.clone();
cv::threshold(
gaussianBlurred,
OutputArray2,
0,
255,
cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
}

int main() {
cv::Mat img;
img = cv::imread("I:\\ProjectArtemis\\OpenCVTest1\\testimg.png");

std::vector contours;
std::vector hierarchy;
cv::Mat edged;
cv::Mat thresh;
PreProcess(img, edged, thresh);
cv::findContours(
edged.clone(),
contours,
hierarchy,
cv::RETR_EXTERNAL,
cv::CHAIN_APPROX_SIMPLE
);

cv::Mat warped;
cv::Mat warped_thresh;
for (const auto& c : contours) {
double peri = 0.01 * cv::arcLength(c, true);
std::vector approx;
cv::approxPolyDP(c, approx, peri, true);

if (approx.size() == 4) {
std::vector points;
for (const auto& point : approx) {
points.push_back(cv::Point2f(point.x, point.y));
}
CorrectPerspective(img, warped, points);
CorrectPerspective(thresh, warped_thresh, points);
}
}

cv::Mat opt;
cv::Mat opt_thresh;
PreProcess(warped, opt, opt_thresh); //能跑起来就先别动
std::vector optionContours;
std::vector optionHierarchy;
cv::findContours(
opt.clone(),
optionContours,
optionHierarchy,
cv::RETR_EXTERNAL,
cv::CHAIN_APPROX_SIMPLE
);

cv::cvtColor(warped_thresh, warped_thresh, cv::COLOR_GRAY2BGR);

std::vector options;
std::vector boundingRects;
for (size_t i = 0; i < optionContours.size(); i++) {
cv::Rect bounding = cv::boundingRect(optionContours);
int x = bounding.x;
int y = bounding.y;
int w = bounding.width;
int h = bounding.height;

float ar = w / static_cast(h);

if (w >= 25 && h >= 25 && ar >= 0.6 && ar

Подробнее здесь: https://stackoverflow.com/questions/792 ... swer-sheet
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»