Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8512deb

Browse filesBrowse files
authored
Merge pull request #23436 from siilats:patch-2
Fix python bindings for setCharucoParameters #23436 setCharucoParameters fails in python Fixes: #23440 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
1 parent aa17f88 commit 8512deb
Copy full SHA for 8512deb

File tree

Expand file treeCollapse file tree

2 files changed

+161
-1
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+161
-1
lines changed

‎modules/objdetect/include/opencv2/objdetect/charuco_detector.hpp

Copy file name to clipboardExpand all lines: modules/objdetect/include/opencv2/objdetect/charuco_detector.hpp
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace aruco {
1313
//! @{
1414

1515
struct CV_EXPORTS_W_SIMPLE CharucoParameters {
16-
CharucoParameters() {
16+
CV_WRAP CharucoParameters() {
1717
minMarkers = 2;
1818
tryRefineMarkers = false;
1919
}

‎modules/objdetect/misc/python/test/test_objdetect_aruco.py

Copy file name to clipboardExpand all lines: modules/objdetect/misc/python/test/test_objdetect_aruco.py
+160Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,96 @@
44
from __future__ import print_function
55

66
import os, tempfile, numpy as np
7+
from math import pi
78

89
import cv2 as cv
910

1011
from tests_common import NewOpenCVTests
1112

13+
def getSyntheticRT(yaw, pitch, distance):
14+
rvec = np.zeros((3, 1), np.float64)
15+
tvec = np.zeros((3, 1), np.float64)
16+
17+
rotPitch = np.array([[-pitch], [0], [0]])
18+
rotYaw = np.array([[0], [yaw], [0]])
19+
20+
rvec, tvec = cv.composeRT(rotPitch, np.zeros((3, 1), np.float64),
21+
rotYaw, np.zeros((3, 1), np.float64))[:2]
22+
23+
tvec = np.array([[0], [0], [distance]])
24+
return rvec, tvec
25+
26+
# see test_aruco_utils.cpp
27+
def projectMarker(img, board, markerIndex, cameraMatrix, rvec, tvec, markerBorder):
28+
markerSizePixels = 100
29+
markerImg = cv.aruco.generateImageMarker(board.getDictionary(), board.getIds()[markerIndex], markerSizePixels, borderBits=markerBorder)
30+
31+
distCoeffs = np.zeros((5, 1), np.float64)
32+
maxCoord = board.getRightBottomCorner()
33+
objPoints = board.getObjPoints()[markerIndex]
34+
for i in range(len(objPoints)):
35+
objPoints[i][0] -= maxCoord[0] / 2
36+
objPoints[i][1] -= maxCoord[1] / 2
37+
objPoints[i][2] -= maxCoord[2] / 2
38+
39+
corners, _ = cv.projectPoints(objPoints, rvec, tvec, cameraMatrix, distCoeffs)
40+
41+
originalCorners = np.array([
42+
[0, 0],
43+
[markerSizePixels, 0],
44+
[markerSizePixels, markerSizePixels],
45+
[0, markerSizePixels],
46+
], np.float32)
47+
48+
transformation = cv.getPerspectiveTransform(originalCorners, corners)
49+
50+
borderValue = 127
51+
aux = cv.warpPerspective(markerImg, transformation, img.shape, None, cv.INTER_NEAREST, cv.BORDER_CONSTANT, borderValue)
52+
53+
assert(img.shape == aux.shape)
54+
mask = (aux == borderValue).astype(np.uint8)
55+
img = img * mask + aux * (1 - mask)
56+
return img
57+
58+
def projectChessboard(squaresX, squaresY, squareSize, imageSize, cameraMatrix, rvec, tvec):
59+
img = np.ones(imageSize, np.uint8) * 255
60+
distCoeffs = np.zeros((5, 1), np.float64)
61+
for y in range(squaresY):
62+
startY = y * squareSize
63+
for x in range(squaresX):
64+
if (y % 2 != x % 2):
65+
continue
66+
startX = x * squareSize
67+
68+
squareCorners = np.array([[startX - squaresX*squareSize/2,
69+
startY - squaresY*squareSize/2,
70+
0]], np.float32)
71+
squareCorners = np.stack((squareCorners[0],
72+
squareCorners[0] + [squareSize, 0, 0],
73+
squareCorners[0] + [squareSize, squareSize, 0],
74+
squareCorners[0] + [0, squareSize, 0]))
75+
76+
projectedCorners, _ = cv.projectPoints(squareCorners, rvec, tvec, cameraMatrix, distCoeffs)
77+
projectedCorners = projectedCorners.astype(np.int64)
78+
projectedCorners = projectedCorners.reshape(1, 4, 2)
79+
img = cv.fillPoly(img, [projectedCorners], 0)
80+
81+
return img
82+
83+
def projectCharucoBoard(board, cameraMatrix, yaw, pitch, distance, imageSize, markerBorder):
84+
rvec, tvec = getSyntheticRT(yaw, pitch, distance)
85+
86+
img = np.ones(imageSize, np.uint8) * 255
87+
for indexMarker in range(len(board.getIds())):
88+
img = projectMarker(img, board, indexMarker, cameraMatrix, rvec, tvec, markerBorder)
89+
90+
chessboard = projectChessboard(board.getChessboardSize()[0], board.getChessboardSize()[1],
91+
board.getSquareLength(), imageSize, cameraMatrix, rvec, tvec)
92+
93+
chessboard = (chessboard != 0).astype(np.uint8)
94+
img = img * chessboard
95+
return img, rvec, tvec
96+
1297
class aruco_objdetect_test(NewOpenCVTests):
1398

1499
def test_board(self):
@@ -153,5 +238,80 @@ def test_charuco_detector(self):
153238
self.assertEqual(charucoIds[i], i)
154239
np.testing.assert_allclose(gold_corners, charucoCorners.reshape(-1, 2), 0.01, 0.1)
155240

241+
# check no segfault when cameraMatrix or distCoeffs are not initialized
242+
def test_charuco_no_segfault_params(self):
243+
dictionary = cv.aruco.getPredefinedDictionary(cv.aruco.DICT_4X4_1000)
244+
board = cv.aruco.CharucoBoard((10, 10), 0.019, 0.015, dictionary)
245+
charuco_parameters = cv.aruco.CharucoParameters()
246+
detector = cv.aruco.CharucoDetector(board)
247+
detector.setCharucoParameters(charuco_parameters)
248+
249+
self.assertIsNone(detector.getCharucoParameters().cameraMatrix)
250+
self.assertIsNone(detector.getCharucoParameters().distCoeffs)
251+
252+
def test_charuco_no_segfault_params_constructor(self):
253+
dictionary = cv.aruco.getPredefinedDictionary(cv.aruco.DICT_4X4_1000)
254+
board = cv.aruco.CharucoBoard((10, 10), 0.019, 0.015, dictionary)
255+
charuco_parameters = cv.aruco.CharucoParameters()
256+
detector = cv.aruco.CharucoDetector(board, charucoParams=charuco_parameters)
257+
258+
self.assertIsNone(detector.getCharucoParameters().cameraMatrix)
259+
self.assertIsNone(detector.getCharucoParameters().distCoeffs)
260+
261+
# similar to C++ test CV_CharucoDetection.accuracy
262+
def test_charuco_detector_accuracy(self):
263+
iteration = 0
264+
cameraMatrix = np.eye(3, 3, dtype=np.float64)
265+
imgSize = (500, 500)
266+
params = cv.aruco.DetectorParameters()
267+
params.minDistanceToBorder = 3
268+
269+
board = cv.aruco.CharucoBoard((4, 4), 0.03, 0.015, cv.aruco.getPredefinedDictionary(cv.aruco.DICT_6X6_250))
270+
detector = cv.aruco.CharucoDetector(board, detectorParams=params)
271+
272+
cameraMatrix[0, 0] = cameraMatrix[1, 1] = 600
273+
cameraMatrix[0, 2] = imgSize[0] / 2
274+
cameraMatrix[1, 2] = imgSize[1] / 2
275+
276+
# for different perspectives
277+
distCoeffs = np.zeros((5, 1), dtype=np.float64)
278+
for distance in [0.2, 0.4]:
279+
for yaw in range(-55, 51, 25):
280+
for pitch in range(-55, 51, 25):
281+
markerBorder = iteration % 2 + 1
282+
iteration += 1
283+
284+
# create synthetic image
285+
img, rvec, tvec = projectCharucoBoard(board, cameraMatrix, yaw * pi / 180, pitch * pi / 180, distance, imgSize, markerBorder)
286+
287+
params.markerBorderBits = markerBorder
288+
detector.setDetectorParameters(params)
289+
290+
if (iteration % 2 != 0):
291+
charucoParameters = cv.aruco.CharucoParameters()
292+
charucoParameters.cameraMatrix = cameraMatrix
293+
charucoParameters.distCoeffs = distCoeffs
294+
detector.setCharucoParameters(charucoParameters)
295+
296+
charucoCorners, charucoIds, corners, ids = detector.detectBoard(img)
297+
298+
self.assertGreater(len(ids), 0)
299+
300+
copyChessboardCorners = board.getChessboardCorners()
301+
copyChessboardCorners -= np.array(board.getRightBottomCorner()) / 2
302+
303+
projectedCharucoCorners, _ = cv.projectPoints(copyChessboardCorners, rvec, tvec, cameraMatrix, distCoeffs)
304+
305+
if charucoIds is None:
306+
self.assertEqual(iteration, 46)
307+
continue
308+
309+
for i in range(len(charucoIds)):
310+
currentId = charucoIds[i]
311+
self.assertLess(currentId, len(board.getChessboardCorners()))
312+
313+
reprErr = cv.norm(charucoCorners[i] - projectedCharucoCorners[currentId])
314+
self.assertLessEqual(reprErr, 5)
315+
156316
if __name__ == '__main__':
157317
NewOpenCVTests.bootstrap()

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.