Перейти к содержимому
Compvision.ru

nonblizz

Пользователи
  • Количество публикаций

    6
  • Зарегистрирован

  • Посещение

  • Days Won

    2

Все публикации пользователя nonblizz

  1. Доброго времени суток всем! Пишу диплом, где мне необходимо посчитать количество зубьев шестерни на изображении, а также диаметр самой шестеренки. Есть Я выделил контуры изображения вот так (код на Java-обёртке, но не суть) : Mat sourceMat = new Mat(), defaultMat = new Mat(); Utils.bitmapToMat(src, sourceMat); // Матрица изображения для обработки Utils.bitmapToMat(src, defaultMat);// Матрица исходная, для конечной отрисовки Imgproc.cvtColor(sourceMat, sourceMat, Imgproc.COLOR_RGB2GRAY, 4); //Преобразование матрицы в чб Mat blurMat = new Mat(); Mat canMat = new Mat(); Imgproc.blur(sourceMat, canMat, new Size(7,5)); //Сглаживание Imgproc.Canny(canMat, blurMat, 0, 60, 3, false); //Детектор границ Кенни Mat hierarchy = new Mat(); List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Imgproc.findContours(blurMat, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE); Что делать дальше, я не особо понимаю. Прошу вашего совета и помощи. Примеры изображений
  2. Защитил диплом, забыл приложить финальный код, может кому пригодится. Большое спасибо Smorodov и всем отписавшимся. Считаются все необходимые параметры(коэффициент смещения колеса, делительная окружность, модуль колеса). При необходимости реализации масштаба, нужно домножить все параметры на коэффициент масштаба. #include "opencv2/opencv.hpp" #include <iostream> #include <vector> using namespace cv; using namespace std; int main(int ac, char** av) { vector<vector<Point> > contours; vector<Vec4i> hierarchy; vector<RotatedRect> minEllipse; vector<RotatedRect> minRect; string fname; float alpha = 20; if (ac > 1) { fname = av[1]; alpha = ::atof(av[2]); } else { cout << "Need filename!" << endl; cin.get(); return 0; } Mat frame = imread(fname); Mat drawing = frame.clone(); frame = 266 - frame; namedWindow("result"); cvtColor(frame, frame, cv::COLOR_BGR2GRAY); threshold(frame, frame, 1, 255, THRESH_BINARY); Mat thr = frame.clone(); /// Find contours findContours(frame, contours, hierarchy, cv::RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); vector<Point2f>center(contours.size()); vector<float>radius(contours.size()); vector<vector<Point> > contours_poly(contours.size()); for (int i = 0; i < contours.size(); i++) { approxPolyDP(Mat(contours[i]), contours_poly[i], 5, true); minEnclosingCircle((Mat)contours_poly[i], center[i], radius[i]); minRect.push_back(minAreaRect(Mat(contours[i]))); if (contours[i].size() > 5) { minEllipse.push_back(fitEllipse(Mat(contours[i]))); } } RNG rng(12345); for (int i = 0; i< contours.size(); i++) { Scalar color = Scalar(255, 0, 0); // contour drawContours(drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point()); // ellipse ellipse(drawing, minEllipse[i], color, 0, 8); // rotated rectangle Point2f rect_points[4]; minRect[i].points(rect_points); for (int j = 0; j < 4; j++) line(drawing, rect_points[j], rect_points[(j + 1) % 4], color, 1, 8); // окружность circle(drawing, center[i], cvRound(radius[i]), color, 1, 8, 0); // ÷ентр окружности line(drawing, cv::Point(center[i].x, 0), cv::Point(center[i].x, drawing.rows), Scalar(0, 0, 255)); line(drawing, cv::Point(0, center[i].y), cv::Point(drawing.cols, center[i].y), Scalar(0, 0, 255)); } // засемплим точки с окружности. float step = 0.001; float x = center[0].x; float y = center[0].y; float r = radius[0] * 0.9; Mat unrolled = Mat::zeros(100, CV_PI*2.0 / step, CV_8UC1); int i = 0; int tooth_thick = 0; vector<int> teeth; bool tooth = false; float normals[2][2]; for (float ang = 0; ang<CV_PI * 2; ang += step) { float xs = x + r*cos(ang); float ys = y + r*sin(ang); uchar c = thr.at<uchar>(ys, xs); drawing.at<Vec3b>(ys, xs) = Vec3b(0, 0, 255); if (c>128) { if (teeth.size() == 1 && tooth == false) { normals[0][0] = xs; normals[0][1] = ys; } tooth = true; tooth_thick++; line(unrolled, cv::Point(i, 0), cv::Point(i, unrolled.rows), Scalar::all(255),5); } else { if (tooth) { teeth.push_back(tooth_thick); tooth_thick = 0; //count++; if (teeth.size() == 1) { normals[1][0] = xs; normals[1][1] = ys; } } tooth = false; } ++i; } //do normals to surface of teeth //line(drawing, Point(normals[0][0], normals[0][1]), Point(800 * cos(alpha * 180 / CV_PI), normals[0][1] * sin(alpha * 180 / CV_PI)), Scalar(0, 255, 0), 1); //line(drawing, Point(normals[1][0], normals[1][1]), Point(800 * cos(alpha * 180 / CV_PI), normals[1][1] * sin(alpha * 180 / CV_PI)), Scalar(0, 255, 0), 1); float m = minRect[0].size.width/(teeth.size()+2);//модуль float d = m*teeth.size();//delitelnaya okrujnost float Db = d*::cos(alpha); float sb = (CV_PI*m) / 2; //tolshina po delitelnoy okrujnosti alpha = alpha * CV_PI / 180;//for invol (convert deg to radian) float X = ((normals[0][1] - normals[1][1]) - (Db*(sb / d + (tan(alpha)-alpha)))) / (2 * m*sin(alpha)); stringstream str; str << "d= " + to_string(minRect[0].size.width) << " "; str << "m= " + to_string(m) << " "; str << "x= " + to_string(X) << " "; //imshow("thr", thr); //imshow("unrolled", unrolled); Mat pic = cv::Mat::zeros(250, 250, CV_8UC3); putText(pic,str.str(), cv::Point(5, 10), CV_FONT_NORMAL, 0.3, Scalar::all(255), 1, 7, false); imshow("Результаты", pic); imshow("result", drawing); waitKey(0); destroyAllWindows(); return 0; }
  3. Проблема в том, что на одном и том же радиусе может быть разное количество зубьев (от 17 до 40), это подбирается исключительно шагом зубьев(его можно было бы вычислить, если бы как-то выделить центр шестерни и радиус высоты головки зуба, чтобы там четко выделялось хотя бы 2 стоящих рядом зуба(затем 360/угол между 2 зубьями и есть количество). Все упирается в эту окружность высоты головки зуба, которую надо как-то выделить (как - я придумать категорически не могу, единственный вариант который приходит в голову (в идеальных условиях), это взять крайний верхний, затем правый, затем левый пиксели (они придутся (по идее) на край одного из зубьев, затем построить окружность по 3м точкам. Нормальная ли это идея?
  4. А если взять такие шестеренки: Как выделить зубья?
  5. Метод Отсу даёт такую картину: У меня так и не получилось убрать эту тень, а также убрать "засветы"
  6. Спасибо за ваши советы. Сделал бинаризацию, выделил границы через Кенни, затем сделал поиск кругов Хафа. Код: Imgproc.cvtColor(sourceImg, sourceImg, Imgproc.COLOR_RGB2GRAY, 4); Imgproc.GaussianBlur(sourceImg,des, new Size(9,9),3,3); Imgproc.threshold(des, des, 30, 1, Imgproc.THRESH_TOZERO); Imgproc.Canny(des, des, 0 , 60); Mat circles = new Mat(); Imgproc.HoughCircles(des, circles, Imgproc.CV_HOUGH_GRADIENT, 1.0, 50, 70.0, 30.0, 100, 0); Вот что получилось (для каждого изображения, что выкладывал в 1ом посте): 1. (Почему-то вообще ни одного круга так и не нашел) 2. (не влезла полностью картинка) 3. 4. И соответственно ряд вопросов: как автоматически подбирать трешхолды (для кенни, сглаживания и бинаризации)? как расширить окружность (вернее, как узнать, насколько расширять окружность)? Заранее извиняюсь, если вопросы глупые, я новичок в openCV.
×