25#include <opencv2/core.hpp>
26#include <opencv2/core/utility.hpp>
27#include <opencv2/imgproc.hpp>
28#include <opencv2/calib3d.hpp>
29#include <opencv2/objdetect/charuco_detector.hpp>
39 Pattern::ChessBoard, Pattern_Values, ParamCateg);
43 aruco::Dict::D4X4_50, aruco::Dict_Values, ParamCateg);
47 "unit used here is the one that will be used once calibrated to report 3D coordinates "
48 "of objects relative to the camera",
53 "etc). The unit used here is the one that will be used once calibrated to report 3D "
54 "coordinates of objects relative to the camera",
59 "vertical tiles/disks. (Note: for asymmetric circle grid, count the number of "
60 "disks on each row, then the number of rows). The product width * height "
61 "should be the total number of tiles/disks on the grid.)",
62 { 11, 7 }, ParamCateg);
70 "not try to optimize them, i.e., assume board is exactly planar",
79 "produces significant barrel distortion, otherwise false",
104 "by fisheye lenses)",
109 "by fisheye lenses)",
118 "detected patterns so far. Click this for at least 5 images showing your calibration board "
119 "under various viewpoints. When enough boards have been successfully captured, click "
125 "enough good views of your calibration board before you can calibrate.",
190 public jevois::Parameter<pattern, dictionary, squareSize, markerSize, boardSize,
191 aspectRatio, zeroTangentDist, fixPrincipalPoint, winSize,
192 fishEye, fixK1, fixK2, fixK3, fixK4, fixK5, fixK6,
193 showUndistorted, grab, calibrate>
218 std::vector<cv::Point2f> pointBuf;
219 int chessBoardFlags = cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_NORMALIZE_IMAGE;
222 if (fishEye::get() ==
false) chessBoardFlags |= cv::CALIB_CB_FAST_CHECK;
225 cv::Size bs = boardSize::get();
228 switch (pattern::get())
230 case Pattern::ChessBoard:
231 found = cv::findChessboardCorners(view, cv::Size(bs.width - 1, bs.height - 1), pointBuf, chessBoardFlags);
236 cv::cvtColor(view, viewGray, cv::COLOR_BGR2GRAY);
237 cv::cornerSubPix(viewGray, pointBuf, cv::Size(winSize::get(), winSize::get()), cv::Size(-1,-1),
238 cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.0001));
242 case Pattern::ChArUcoBoard:
245 if (! itsChArUcoDetector)
249 cv::aruco::CharucoBoard ch_board({boardSize::get().width, boardSize::get().height}, squareSize::get(),
250 markerSize::get(), dico);
251 cv::aruco::DetectorParameters detector_params;
252 detector_params.cornerRefinementMethod = int(cv::aruco::CORNER_REFINE_NONE);
254 cv::aruco::CharucoParameters charuco_params;
255 charuco_params.tryRefineMarkers =
true;
256 charuco_params.cameraMatrix = itsCameraMatrix;
257 charuco_params.distCoeffs = itsDistCoeffs;
258 itsChArUcoDetector.reset(
new cv::aruco::CharucoDetector(ch_board, charuco_params, detector_params));
262 std::vector<int> markerIds, charucoIds;
263 std::vector<std::vector<cv::Point2f> > markerCorners;
264 itsChArUcoDetector->detectBoard(view, pointBuf, charucoIds, markerCorners, markerIds);
265 size_t needed_num = (size_t)((bs.height - 1)*(bs.width - 1));
266 LINFO(
"ChArUco: detected "<< pointBuf.size() <<
" out of " << needed_num <<
" corners");
267 found = (pointBuf.size() == needed_num);
272 LINFO(
"ChArUco calibration board successfully detected");
274 itsImagePoints.push_back(pointBuf);
277 itsLastGoodView = view.clone();
278 itsLastGoodTime = std::chrono::steady_clock::now();
279 if (markerIds.size() > 0)
280 cv::aruco::drawDetectedMarkers(itsLastGoodView, markerCorners);
281 if (charucoIds.size() > 0)
282 cv::aruco::drawDetectedCornersCharuco(itsLastGoodView, pointBuf, charucoIds, cv::Scalar(255, 0, 0));
287 case Pattern::CirclesGrid:
288 found = findCirclesGrid(view, bs, pointBuf);
291 case Pattern::AsymmetricCirclesGrid:
292 found = findCirclesGrid(view, bs, pointBuf, cv::CALIB_CB_ASYMMETRIC_GRID);
297 if (pattern::get() != Pattern::ChArUcoBoard)
300 LINFO(
"Calibration board successfully detected");
302 itsImagePoints.push_back(pointBuf);
305 itsLastGoodView = view.clone();
306 itsLastGoodTime = std::chrono::steady_clock::now();
307 drawChessboardCorners(itsLastGoodView, cv::Size(bs.width - 1, bs.height - 1), cv::Mat(pointBuf), found);
310 else engine()->reportError(
"Calibration board was not detected. Make sure it is in full view with no "
311 "occlusions, reflections, strong shadows, etc.");
315 if (calibrate::get())
317 calibrate::set(
false);
319 if (itsImagePoints.size() < 5)
320 engine()->reportError(
"Need at least 5 good board views before calibration");
325 if (itsCalibrated ==
false)
327 engine()->reportError(
"Calibration failed. Let's try again.");
336 if (showUndistorted::get())
338 itsLastGoodView = cv::Mat();
342 cv::fisheye::estimateNewCameraMatrixForUndistortRectify(itsCameraMatrix, itsDistCoeffs, itsImageSize,
343 cv::Matx33d::eye(), newCamMat, 1);
344 cv::fisheye::undistortImage(view, itsLastGoodView, itsCameraMatrix, itsDistCoeffs, newCamMat);
346 else cv::undistort(view, itsLastGoodView, itsCameraMatrix, itsDistCoeffs);
348 else itsLastGoodView = view;
355 itsCalibrated =
false;
361 itsFlag = cv::fisheye::CALIB_FIX_SKEW | cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;
362 if (fixK1::get()) itsFlag |= cv::fisheye::CALIB_FIX_K1;
363 if (fixK2::get()) itsFlag |= cv::fisheye::CALIB_FIX_K2;
364 if (fixK3::get()) itsFlag |= cv::fisheye::CALIB_FIX_K3;
365 if (fixK4::get()) itsFlag |= cv::fisheye::CALIB_FIX_K4;
366 if (fixPrincipalPoint::get()) itsFlag |= cv::fisheye::CALIB_FIX_PRINCIPAL_POINT;
370 if (fixPrincipalPoint::get()) itsFlag |= cv::CALIB_FIX_PRINCIPAL_POINT;
371 if (zeroTangentDist::get()) itsFlag |= cv::CALIB_ZERO_TANGENT_DIST;
372 if (aspectRatio::get()) itsFlag |= cv::CALIB_FIX_ASPECT_RATIO;
373 if (fixK1::get()) itsFlag |= cv::CALIB_FIX_K1;
374 if (fixK2::get()) itsFlag |= cv::CALIB_FIX_K2;
375 if (fixK3::get()) itsFlag |= cv::CALIB_FIX_K3;
376 if (fixK4::get()) itsFlag |= cv::CALIB_FIX_K4;
377 if (fixK5::get()) itsFlag |= cv::CALIB_FIX_K5;
378 if (fixK6::get()) itsFlag |= cv::CALIB_FIX_K6;
381 std::vector<cv::Mat> rvecs, tvecs;
382 std::vector<float> reprojErrs;
383 std::vector<cv::Point3f> newObjPoints;
385 itsCalibrated =
runCalibration(rvecs, tvecs, reprojErrs, itsAvgErr, newObjPoints);
391 calib.
sensor = engine()->camerasens::get();
392 calib.
lens = engine()->cameralens::get();
393 calib.
fisheye = fishEye::get();
394 calib.
w = itsImageSize.width;
395 calib.
h = itsImageSize.height;
400 engine()->saveCameraCalibration(calib);
406 std::vector<cv::Mat>
const & rvecs, std::vector<cv::Mat>
const & tvecs,
407 std::vector<float> & perViewErrors)
409 std::vector<cv::Point2f> imagePoints2;
410 size_t totalPoints = 0;
411 double totalErr = 0, err;
412 perViewErrors.resize(objectPoints.size());
414 for (
size_t i = 0; i < objectPoints.size(); ++i )
417 cv::fisheye::projectPoints(objectPoints[i], imagePoints2, rvecs[i], tvecs[i], itsCameraMatrix, itsDistCoeffs);
419 cv::projectPoints(objectPoints[i], rvecs[i], tvecs[i], itsCameraMatrix, itsDistCoeffs, imagePoints2);
421 err = cv::norm(itsImagePoints[i], imagePoints2, cv::NORM_L2);
423 size_t n = objectPoints[i].size();
424 perViewErrors[i] = (float) std::sqrt(err*err/n);
429 return std::sqrt(totalErr / totalPoints);
437 switch (pattern::get())
439 case Pattern::ChessBoard:
440 case Pattern::CirclesGrid:
441 for (
int i = 0; i < boardsiz.height - 1; ++i)
442 for (
int j = 0; j < boardsiz.width - 1; ++j)
443 corners.push_back(cv::Point3f(j*squaresiz, i*squaresiz, 0));
446 case Pattern::ChArUcoBoard:
447 for (
int i = 0; i < boardsiz.height - 1; ++i)
448 for (
int j = 0; j < boardsiz.width - 1; ++j)
449 corners.push_back(cv::Point3f(j*squaresiz, i*squaresiz, 0));
452 case Pattern::AsymmetricCirclesGrid:
453 for (
int i = 0; i < boardsiz.height - 1; i++)
454 for (
int j = 0; j < boardsiz.width - 1; j++)
455 corners.push_back(cv::Point3f((2 * j + i % 2)*squaresiz, i*squaresiz, 0));
461 bool runCalibration(std::vector<cv::Mat> & rvecs, std::vector<cv::Mat> & tvecs, std::vector<float> & reprojErrs,
462 double & totalAvgErr, std::vector<cv::Point3f> & newObjPoints)
464 itsCameraMatrix = cv::Mat::eye(3, 3, CV_64F);
465 if (fishEye::get() ==
false && itsFlag & cv::CALIB_FIX_ASPECT_RATIO)
466 itsCameraMatrix.at<
double>(0,0) = aspectRatio::get();
467 if (fishEye::get()) itsDistCoeffs = cv::Mat::zeros(4, 1, CV_64F);
468 else itsDistCoeffs = cv::Mat::zeros(8, 1, CV_64F);
470 std::vector<std::vector<cv::Point3f> > objectPoints(1);
472 newObjPoints = objectPoints[0];
474 objectPoints.resize(itsImagePoints.size(), objectPoints[0]);
481 cv::Mat _rvecs, _tvecs;
482 rms = cv::fisheye::calibrate(objectPoints, itsImagePoints, itsImageSize, itsCameraMatrix, itsDistCoeffs,
483 _rvecs, _tvecs, itsFlag);
485 rvecs.reserve(_rvecs.rows);
486 tvecs.reserve(_tvecs.rows);
487 for (
int i = 0; i < int(objectPoints.size()); i++)
489 rvecs.push_back(_rvecs.row(i));
490 tvecs.push_back(_tvecs.row(i));
495 int iFixedPoint = -1;
496 rms = cv::calibrateCameraRO(objectPoints, itsImagePoints, itsImageSize, iFixedPoint,
497 itsCameraMatrix, itsDistCoeffs, rvecs, tvecs, newObjPoints,
498 itsFlag | cv::CALIB_USE_LU);
501 LINFO(
"Re-projection error reported by calibrateCamera: "<< rms);
503 bool ok = cv::checkRange(itsCameraMatrix) && cv::checkRange(itsDistCoeffs);
505 objectPoints.clear();
506 objectPoints.resize(itsImagePoints.size(), newObjPoints);
526 inimg.
require(
"input", w,
h, V4L2_PIX_FMT_YUYV);
529 itsImageSize.width = w; itsImageSize.height =
h;
534 outimg = outframe.get();
535 outimg.
require(
"output", w, 2*
h + 15, V4L2_PIX_FMT_YUYV);
554 int y = 15, y2 =
h + 3;
557 if (itsLastGoodView.empty() ==
false)
564 if (showUndistorted::get())
577 if (itsImagePoints.size() >= 5)
591 std::string
const & fpscpu = timer.
stop();
607 unsigned short winw, winh;
611 int x = 0, y = 0;
unsigned short iw = 0, ih = 0;
613 helper.
itext(
"JeVois-Pro Camera Calibration");
616 cv::Mat cvimg = inframe.getCvRGBp();
617 itsImageSize.width = cvimg.cols;
618 itsImageSize.height = cvimg.rows;
629 helper.
itext(
"Camera is now calibrated - average reprojection error = " + std::to_string(itsAvgErr));
630 if (showUndistorted::get())
631 helper.
itext(
"Showing undistorted view. Turn off showUndistorted to see normal view");
633 helper.
itext(
"Showing normal view. Turn on showUndistorted to see undistorted view");
635 int vx = 0, vy = 0;
unsigned short vw = 0, vh = 0;
636 helper.
drawImage(
"v", itsLastGoodView,
true , vx, vy, vw, vh,
false,
true);
641 helper.
itext(
"Good calibration board views so far: " + std::to_string(itsImagePoints.size()));
642 if (itsImagePoints.size() >= 5)
643 helper.
itext(
"Enough good board views acquired for calibration, you may grab more to improve accuracy,"
644 " or calibrate now.");
646 helper.
itext(
"Need at least 5 good board views for calibration, keep grabbing, use varied viewpoints");
649 std::chrono::duration<float>
const elapsed = std::chrono::steady_clock::now() - itsLastGoodTime;
650 if (elapsed.count() < 2.0F && itsLastGoodView.empty() ==
false)
652 helper.
itext(
"Calibration board successfully detected");
653 int vx = 0, vy = 0;
unsigned short vw = 0, vh = 0;
654 helper.
drawImage(
"v", itsLastGoodView,
true , vx, vy, vw, vh,
false,
true);
661 ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
662 ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
665 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xf0ffe0e0);
667 if (ImGui::Begin(
"Calibrate Camera Controls"))
669 int wrap = ImGui::GetWindowSize().x - ImGui::GetFontSize() * 2.0f;
670 ImGui::PushTextWrapPos(wrap);
674 ImGui::TextUnformatted(
"Camera is now calibrated and calibration was saved to disk.");
675 ImGui::TextUnformatted(
"");
676 ImGui::Text(
"Average reprojection error: %f (lower is better)", itsAvgErr);
677 ImGui::TextUnformatted(
"");
680 if (ImGui::Button(
"Grab more views")) itsCalibrated =
false;
682 else if (itsReady ==
false)
684 if (itsImagePoints.empty())
686 ImGui::TextUnformatted(
"To get started, switch to the Parameters tab of the main window, "
687 "and set some parameters.");
688 ImGui::TextUnformatted(
"");
689 ImGui::TextUnformatted(
"Critical parameters are:");
690 ImGui::TextUnformatted(
"");
692 ImGui::Text(
"pattern - choose a board type (chessboard, ChArUco, etc)");
694 ImGui::Text(
"fishEye - whether you are using a fish-eye (wide angle) lens");
696 ImGui::Text(
"squareSize - physical size in your chosen units (mm, inch, etc) of one board square");
698 ImGui::Text(
"markerSize - if using ChArUco, physical size of markers in your units");
700 ImGui::Text(
"boardSize - horizontal and vertical number of tiles");
702 ImGui::Text(
"engine::cameralens - lens you are calibrating (in System Parameters)");
704 ImGui::TextUnformatted(
"");
707 itsReady = ImGui::Button(
"Ready!");
711 ImGui::Text(
"Sensor: %s, Lens: %s, Resolution: %dx%d",
712 engine()->camerasens::strget().c_str(), engine()->cameralens::strget().c_str(),
713 itsImageSize.width, itsImageSize.height);
715 ImGui::TextUnformatted(
"Point the camera so that you get a full view of the calibration board, "
717 if (itsImagePoints.empty() ==
false)
719 ImGui::TextUnformatted(
"");
720 ImGui::TextUnformatted(
"Move the camera around to get a variety of viewpoints.");
721 ImGui::TextUnformatted(
"Need at least 5 valid viewpoints. The more the better.");
722 ImGui::TextUnformatted(
"");
723 ImGui::Text(
"Good board views so far: %zu", itsImagePoints.size());
725 ImGui::TextUnformatted(
"");
727 if (ImGui::Button(
"Grab")) grab::set(
true);
729 if (itsImagePoints.size() >= 5)
731 ImGui::SameLine(); ImGui::TextUnformatted(
" "); ImGui::SameLine();
732 if (ImGui::Button(
"Calibrate now")) calibrate::set(
true);
735 ImGui::SameLine(); ImGui::TextUnformatted(
" "); ImGui::SameLine();
736 if (ImGui::Button(
"Drop last grab") && itsImagePoints.empty() ==
false) itsImagePoints.pop_back();
742 ImGui::SameLine(); ImGui::TextUnformatted(
" "); ImGui::SameLine();
743 if (ImGui::Button(
"Start over"))
restart();
746 ImGui::PopTextWrapPos();
750 ImGui::PopStyleColor();
753 std::string
const & fpscpu = timer.
stop();
754 helper.
iinfo(inframe, fpscpu, winw, winh);
765 itsChArUcoDetector.reset();
768 itsCalibrated =
false;
769 itsImagePoints.clear();
778 bool itsReady =
false;
779 bool itsCalibrated =
false;
781 cv::Size itsImageSize;
782 std::vector<std::vector<cv::Point2f> > itsImagePoints;
783 cv::Mat itsCameraMatrix = cv::Mat::eye(3, 3, CV_64F);
784 cv::Mat itsDistCoeffs = cv::Mat::zeros(8, 1, CV_64F);
785 cv::Mat itsLastGoodView;
786 std::chrono::time_point<std::chrono::steady_clock> itsLastGoodTime;
787 std::shared_ptr<cv::aruco::CharucoDetector> itsChArUcoDetector;
788 double itsAvgErr = 0.0;
JEVOIS_REGISTER_MODULE(ArUcoBlob)
static cv::aruco::Dictionary getDictionary(aruco::Dict d)
Static method to allow anyone to get the ArUco dictionary for a given value of our dictionary paramet...
Helper module to calibrate a given sensor+lens combo, which allows ArUco and other modules to do 3D p...
JEVOIS_DECLARE_PARAMETER(fishEye, bool, "Use fisheye model. Should be true if using a wide-angle lens that " "produces significant barrel distortion, otherwise false", false, ParamCateg)
Parameter.
JEVOIS_DEFINE_ENUM_CLASS(Pattern,(ChessBoard)(ChArUcoBoard)(CirclesGrid)(AsymmetricCirclesGrid))
Enum for parameter.
JEVOIS_DECLARE_PARAMETER(aspectRatio, float, "Fixed aspect ratio value to use when non-zero, or auto when 0.0", 0.0F, ParamCateg)
Parameter.
void process_frame(cv::Mat const &view)
Process one captured image.
void calcBoardCornerPositions(cv::Size boardsiz, float squaresiz, std::vector< cv::Point3f > &corners)
JEVOIS_DECLARE_PARAMETER(fixPrincipalPoint, bool, "Fix principal point at center, otherwise find its location", true, ParamCateg)
Parameter.
JEVOIS_DECLARE_PARAMETER(fixK1, bool, "Fix (do not try to optimize) K1 radial distortion parameter", false, ParamCateg)
Parameter.
JEVOIS_DECLARE_PARAMETER(winSize, unsigned char, "Half of search window size for sub-pixel corner refinement", 11, ParamCateg)
Parameter.
double computeReprojectionErrors(std::vector< std::vector< cv::Point3f > > const &objectPoints, std::vector< cv::Mat > const &rvecs, std::vector< cv::Mat > const &tvecs, std::vector< float > &perViewErrors)
JEVOIS_DECLARE_PARAMETER(fixK2, bool, "Fix (do not try to optimize) K2 radial distortion parameter", false, ParamCateg)
Parameter.
JEVOIS_DECLARE_PARAMETER(fixK3, bool, "Fix (do not try to optimize) K3 radial distortion parameter", false, ParamCateg)
Parameter.
JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(dictionary, aruco::Dict, "ArUco dictionary to use", aruco::Dict::D4X4_50, aruco::Dict_Values, ParamCateg)
Parameter.
JEVOIS_DECLARE_PARAMETER(showUndistorted, bool, "Once calibrated, show undistorted image instead of original capture", false, ParamCateg)
Parameter.
virtual void onParamChange(pattern const &par, Pattern const &val)
Restart when some critical params are changed:
virtual void process(jevois::InputFrame &&inframe, jevois::GUIhelper &helper) override
Processing function with zero-copy and GUI on JeVois-Pro.
bool runCalibration(std::vector< cv::Mat > &rvecs, std::vector< cv::Mat > &tvecs, std::vector< float > &reprojErrs, double &totalAvgErr, std::vector< cv::Point3f > &newObjPoints)
JEVOIS_DECLARE_PARAMETER(squareSize, float, "Size of each tile (check) in user-chosen units (e.g., mm, inch, etc). The " "unit used here is the one that will be used once calibrated to report 3D coordinates " "of objects relative to the camera", 23.0f, ParamCateg)
Parameter.
virtual void process(jevois::InputFrame &&inframe, jevois::OutputFrame &&outframe) override
Processing function with video output to USB.
JEVOIS_DECLARE_PARAMETER(markerSize, float, "ChArUco marker size in user-chosen units (e.g., mm, inch, " "etc). The unit used here is the one that will be used once calibrated to report 3D " "coordinates of objects relative to the camera", 27.0f, ParamCateg)
Parameter.
virtual void onParamChange(dictionary const &par, aruco::Dict const &val)
JEVOIS_DECLARE_PARAMETER(fixK5, bool, "Fix (do not try to optimize) K5 radial distortion parameter (not used " "by fisheye lenses)", false, ParamCateg)
Parameter.
JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(boardSize, cv::Size, "Board size [width height] in number of horizontal and " "vertical tiles/disks. (Note: for asymmetric circle grid, count the number of " "disks on each row, then the number of rows). The product width * height " "should be the total number of tiles/disks on the grid.)", { 11, 7 }, ParamCateg)
Parameter.
JEVOIS_DECLARE_PARAMETER(calibrate, bool, "Calibrate using all the grabbed boards so far. You first need to grab " "enough good views of your calibration board before you can calibrate.", false, ParamCateg)
Parameter.
JEVOIS_DECLARE_PARAMETER(fixK6, bool, "Fix (do not try to optimize) K6 radial distortion parameter (not used " "by fisheye lenses)", false, ParamCateg)
Parameter.
JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(pattern, Pattern, "Type of calibration board pattern to use", Pattern::ChessBoard, Pattern_Values, ParamCateg)
Parameter.
JEVOIS_DECLARE_PARAMETER(grab, bool, "Grab one image, try to detect the calibration pattern, and add to list of " "detected patterns so far. Click this for at least 5 images showing your calibration board " "under various viewpoints. When enough boards have been successfully captured, click " "'calibrate'", false, ParamCateg)
Parameter.
virtual ~CalibrateCamera()
Virtual destructor for safe inheritance.
JEVOIS_DECLARE_PARAMETER(zeroTangentDist, bool, "Assume zero tangential distortion coefficients P1, P2 and do " "not try to optimize them, i.e., assume board is exactly planar", true, ParamCateg)
Parameter.
virtual void onParamChange(boardSize const &par, cv::Size const &val)
JEVOIS_DECLARE_PARAMETER(fixK4, bool, "Fix (do not try to optimize) K4 radial distortion parameter", false, ParamCateg)
Parameter.
jevois::CameraSensor sensor
friend friend class Module
void drawInputFrame(char const *name, InputFrame const &frame, int &x, int &y, unsigned short &w, unsigned short &h, bool noalias=false, bool casync=false)
bool startFrame(unsigned short &w, unsigned short &h)
void iinfo(jevois::InputFrame const &inframe, std::string const &fpscpu, unsigned short winw=0, unsigned short winh=0)
void itext(char const *txt, ImU32 const &col=IM_COL32_BLACK_TRANS, int line=-1)
void drawImage(char const *name, RawImage const &img, int &x, int &y, unsigned short &w, unsigned short &h, bool noalias=false, bool isoverlay=false)
void require(char const *info, unsigned int w, unsigned int h, unsigned int f) const
std::string const & stop(double *seconds)
void paste(RawImage const &src, RawImage &dest, int dx, int dy)
void writeText(RawImage &img, std::string const &txt, int x, int y, unsigned int col, Font font=Font6x10)
void drawFilledRect(RawImage &img, int x, int y, unsigned int w, unsigned int h, unsigned int col)
cv::Mat convertToCvBGR(RawImage const &src)
int itext(RawImage &img, std::string const &txt, int y=3, unsigned int col=jevois::yuyv::White, Font font=Font6x10)
void pasteBGRtoYUYV(cv::Mat const &src, RawImage &dst, int dx, int dy)
std::future< std::invoke_result_t< std::decay_t< Function >, std::decay_t< Args >... > > async(Function &&f, Args &&... args)
unsigned short constexpr Black
unsigned short constexpr White