fix drawDetectedCornersCharuco, drawDetectedMarkers, drawDetectedDiamonds added tests

pull/24247/head
Alex 1 year ago
parent 757d296382
commit ae1d1b6d55
  1. 64
      modules/objdetect/misc/python/test/test_objdetect_aruco.py
  2. 18
      modules/objdetect/src/aruco/aruco_detector.cpp
  3. 41
      modules/objdetect/src/aruco/charuco_detector.cpp
  4. 52
      modules/objdetect/test/test_charucodetection.cpp

@ -394,5 +394,69 @@ class aruco_objdetect_test(NewOpenCVTests):
self.assertEqual(2, img_points.shape[2])
np.testing.assert_array_equal(chessboard_corners, obj_points[:, :, :2].reshape(-1, 2))
def test_draw_detected_markers(self):
detected_points = [[[10, 10], [50, 10], [50, 50], [10, 50]]]
img = np.zeros((60, 60), dtype=np.uint8)
# add extra dimension in Python to create Nx4 Mat with 2 channels
points1 = np.array(detected_points).reshape(-1, 4, 1, 2)
img = cv.aruco.drawDetectedMarkers(img, points1, borderColor=255)
# check that the marker borders are painted
contours, _ = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
self.assertEqual(len(contours), 1)
self.assertEqual(img[10, 10], 255)
self.assertEqual(img[50, 10], 255)
self.assertEqual(img[50, 50], 255)
self.assertEqual(img[10, 50], 255)
# must throw Exception without extra dimension
points2 = np.array(detected_points)
with self.assertRaises(Exception):
img = cv.aruco.drawDetectedMarkers(img, points2, borderColor=255)
def test_draw_detected_charuco(self):
detected_points = [[[10, 10], [50, 10], [50, 50], [10, 50]]]
img = np.zeros((60, 60), dtype=np.uint8)
# add extra dimension in Python to create Nx1 Mat with 2 channels
points = np.array(detected_points).reshape(-1, 1, 2)
img = cv.aruco.drawDetectedCornersCharuco(img, points, cornerColor=255)
# check that the 4 charuco corners are painted
contours, _ = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
self.assertEqual(len(contours), 4)
for contour in contours:
center_x = round(np.average(contour[:, 0, 0]))
center_y = round(np.average(contour[:, 0, 1]))
center = [center_x, center_y]
self.assertTrue(center in detected_points[0])
# must throw Exception without extra dimension
points2 = np.array(detected_points)
with self.assertRaises(Exception):
img = cv.aruco.drawDetectedCornersCharuco(img, points2, borderColor=255)
def test_draw_detected_diamonds(self):
detected_points = [[[10, 10], [50, 10], [50, 50], [10, 50]]]
img = np.zeros((60, 60), dtype=np.uint8)
# add extra dimension in Python to create Nx4 Mat with 2 channels
points = np.array(detected_points).reshape(-1, 4, 1, 2)
img = cv.aruco.drawDetectedDiamonds(img, points, borderColor=255)
# check that the diamonds borders are painted
contours, _ = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
self.assertEqual(len(contours), 1)
self.assertEqual(img[10, 10], 255)
self.assertEqual(img[50, 10], 255)
self.assertEqual(img[50, 50], 255)
self.assertEqual(img[10, 50], 255)
# must throw Exception without extra dimension
points2 = np.array(detected_points)
with self.assertRaises(Exception):
img = cv.aruco.drawDetectedDiamonds(img, points2, borderColor=255)
if __name__ == '__main__':
NewOpenCVTests.bootstrap()

@ -1315,24 +1315,26 @@ void drawDetectedMarkers(InputOutputArray _image, InputArrayOfArrays _corners,
int nMarkers = (int)_corners.total();
for(int i = 0; i < nMarkers; i++) {
Mat currentMarker = _corners.getMat(i);
CV_Assert(currentMarker.total() == 4 && currentMarker.type() == CV_32FC2);
CV_Assert(currentMarker.total() == 4 && currentMarker.channels() == 2);
if (currentMarker.type() != CV_32SC2)
currentMarker.convertTo(currentMarker, CV_32SC2);
// draw marker sides
for(int j = 0; j < 4; j++) {
Point2f p0, p1;
p0 = currentMarker.ptr<Point2f>(0)[j];
p1 = currentMarker.ptr<Point2f>(0)[(j + 1) % 4];
Point p0, p1;
p0 = currentMarker.ptr<Point>(0)[j];
p1 = currentMarker.ptr<Point>(0)[(j + 1) % 4];
line(_image, p0, p1, borderColor, 1);
}
// draw first corner mark
rectangle(_image, currentMarker.ptr<Point2f>(0)[0] - Point2f(3, 3),
currentMarker.ptr<Point2f>(0)[0] + Point2f(3, 3), cornerColor, 1, LINE_AA);
rectangle(_image, currentMarker.ptr<Point>(0)[0] - Point(3, 3),
currentMarker.ptr<Point>(0)[0] + Point(3, 3), cornerColor, 1, LINE_AA);
// draw ID
if(_ids.total() != 0) {
Point2f cent(0, 0);
Point cent(0, 0);
for(int p = 0; p < 4; p++)
cent += currentMarker.ptr<Point2f>(0)[p];
cent += currentMarker.ptr<Point>(0)[p];
cent = cent / 4.;
stringstream s;
s << "id=" << _ids.getMat().ptr<int>(0)[i];

@ -507,20 +507,27 @@ void drawDetectedCornersCharuco(InputOutputArray _image, InputArray _charucoCorn
InputArray _charucoIds, Scalar cornerColor) {
CV_Assert(!_image.getMat().empty() &&
(_image.getMat().channels() == 1 || _image.getMat().channels() == 3));
CV_Assert((_charucoCorners.getMat().total() == _charucoIds.getMat().total()) ||
_charucoIds.getMat().total() == 0);
size_t nCorners = _charucoCorners.getMat().total();
CV_Assert((_charucoCorners.total() == _charucoIds.total()) ||
_charucoIds.total() == 0);
CV_Assert(_charucoCorners.channels() == 2);
Mat charucoCorners = _charucoCorners.getMat();
if (charucoCorners.type() != CV_32SC2)
charucoCorners.convertTo(charucoCorners, CV_32SC2);
Mat charucoIds;
if (!_charucoIds.empty())
charucoIds = _charucoIds.getMat();
size_t nCorners = charucoCorners.total();
for(size_t i = 0; i < nCorners; i++) {
Point2f corner = _charucoCorners.getMat().at<Point2f>((int)i);
Point corner = charucoCorners.at<Point>((int)i);
// draw first corner mark
rectangle(_image, corner - Point2f(3, 3), corner + Point2f(3, 3), cornerColor, 1, LINE_AA);
rectangle(_image, corner - Point(3, 3), corner + Point(3, 3), cornerColor, 1, LINE_AA);
// draw ID
if(!_charucoIds.empty()) {
int id = _charucoIds.getMat().at<int>((int)i);
int id = charucoIds.at<int>((int)i);
stringstream s;
s << "id=" << id;
putText(_image, s.str(), corner + Point2f(5, -5), FONT_HERSHEY_SIMPLEX, 0.5,
putText(_image, s.str(), corner + Point(5, -5), FONT_HERSHEY_SIMPLEX, 0.5,
cornerColor, 2);
}
}
@ -540,25 +547,27 @@ void drawDetectedDiamonds(InputOutputArray _image, InputArrayOfArrays _corners,
int nMarkers = (int)_corners.total();
for(int i = 0; i < nMarkers; i++) {
Mat currentMarker = _corners.getMat(i);
CV_Assert(currentMarker.total() == 4 && currentMarker.type() == CV_32FC2);
CV_Assert(currentMarker.total() == 4 && currentMarker.channels() == 2);
if (currentMarker.type() != CV_32SC2)
currentMarker.convertTo(currentMarker, CV_32SC2);
// draw marker sides
for(int j = 0; j < 4; j++) {
Point2f p0, p1;
p0 = currentMarker.at< Point2f >(j);
p1 = currentMarker.at< Point2f >((j + 1) % 4);
Point p0, p1;
p0 = currentMarker.at<Point>(j);
p1 = currentMarker.at<Point>((j + 1) % 4);
line(_image, p0, p1, borderColor, 1);
}
// draw first corner mark
rectangle(_image, currentMarker.at< Point2f >(0) - Point2f(3, 3),
currentMarker.at< Point2f >(0) + Point2f(3, 3), cornerColor, 1, LINE_AA);
rectangle(_image, currentMarker.at<Point>(0) - Point(3, 3),
currentMarker.at<Point>(0) + Point(3, 3), cornerColor, 1, LINE_AA);
// draw id composed by four numbers
if(_ids.total() != 0) {
Point2f cent(0, 0);
Point cent(0, 0);
for(int p = 0; p < 4; p++)
cent += currentMarker.at< Point2f >(p);
cent += currentMarker.at<Point>(p);
cent = cent / 4.;
stringstream s;
s << "id=" << _ids.getMat().at< Vec4i >(i);

@ -689,6 +689,58 @@ TEST(Charuco, testmatchImagePoints)
}
}
typedef testing::TestWithParam<int> CharucoDraw;
INSTANTIATE_TEST_CASE_P(/**/, CharucoDraw, testing::Values(CV_8UC2, CV_8SC2, CV_16UC2, CV_16SC2, CV_32SC2, CV_32FC2, CV_64FC2));
TEST_P(CharucoDraw, testDrawDetected) {
vector<vector<Point>> detected_golds = {{Point(20, 20), Point(80, 20), Point(80, 80), Point2f(20, 80)}};
Point center_gold = (detected_golds[0][0] + detected_golds[0][1] + detected_golds[0][2] + detected_golds[0][3]) / 4;
int type = GetParam();
vector<Mat> detected(detected_golds[0].size(), Mat(4, 1, type));
// copy detected_golds to detected with any 2 channels type
for (size_t i = 0ull; i < detected_golds[0].size(); i++) {
detected[0].row((int)i) = Scalar(detected_golds[0][i].x, detected_golds[0][i].y);
}
vector<vector<Point>> contours;
Point detectedCenter;
Moments m;
Mat img;
// check drawDetectedMarkers
img = Mat::zeros(100, 100, CV_8UC1);
ASSERT_NO_THROW(aruco::drawDetectedMarkers(img, detected, noArray(), Scalar(255, 255, 255)));
// check that the marker borders are painted
findContours(img, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
ASSERT_EQ(contours.size(), 1ull);
m = moments(contours[0]);
detectedCenter = Point(cvRound(m.m10/m.m00), cvRound(m.m01/m.m00));
ASSERT_EQ(detectedCenter, center_gold);
// check drawDetectedCornersCharuco
img = Mat::zeros(100, 100, CV_8UC1);
ASSERT_NO_THROW(aruco::drawDetectedCornersCharuco(img, detected[0], noArray(), Scalar(255, 255, 255)));
// check that the 4 charuco corners are painted
findContours(img, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
ASSERT_EQ(contours.size(), 4ull);
for (size_t i = 0ull; i < 4ull; i++) {
m = moments(contours[i]);
detectedCenter = Point(cvRound(m.m10/m.m00), cvRound(m.m01/m.m00));
// detectedCenter must be in detected_golds
ASSERT_TRUE(find(detected_golds[0].begin(), detected_golds[0].end(), detectedCenter) != detected_golds[0].end());
}
// check drawDetectedDiamonds
img = Mat::zeros(100, 100, CV_8UC1);
ASSERT_NO_THROW(aruco::drawDetectedDiamonds(img, detected, noArray(), Scalar(255, 255, 255)));
// check that the diamonds borders are painted
findContours(img, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
ASSERT_EQ(contours.size(), 1ull);
m = moments(contours[0]);
detectedCenter = Point(cvRound(m.m10/m.m00), cvRound(m.m01/m.m00));
ASSERT_EQ(detectedCenter, center_gold);
}
typedef testing::TestWithParam<cv::Size> CharucoBoard;
INSTANTIATE_TEST_CASE_P(/**/, CharucoBoard, testing::Values(Size(3, 2), Size(3, 2), Size(6, 2), Size(2, 6),
Size(3, 4), Size(4, 3), Size(7, 3), Size(3, 7)));

Loading…
Cancel
Save