32 #include <mrpt/3rdparty/do_opencv_includes.h>
37 #include <mexplus/mxarray.h>
75 : std::runtime_error(s)
86 #define IMAGE_ALLOC_PERFLOG 0
88 #if IMAGE_ALLOC_PERFLOG
107 template <
typename RET = u
int32_t>
122 return std::numeric_limits<RET>::max();
124 template <
typename RET = u
int32_t>
139 return std::numeric_limits<RET>::max();
159 #endif // MRPT_HAS_OPENCV
166 unsigned int width,
unsigned int height,
TImageChannels nChannels)
170 resize(width, height, nChannels);
192 m_impl->img = img.clone();
202 CImage(img.m_impl->img, copy_type)
216 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
224 out_img =
m_impl->img.clone();
236 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
246 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
262 if (
static_cast<unsigned>(
m_impl->img.cols) == width &&
263 static_cast<unsigned>(
m_impl->img.rows) == height &&
264 m_impl->img.channels() == nChannels &&
271 #if IMAGE_ALLOC_PERFLOG
272 const std::string sLog =
mrpt::format(
"cvCreateImage %ux%u", width, height);
273 alloc_tims.enter(sLog.c_str());
280 static_cast<int>(height),
static_cast<int>(width),
281 pixelDepth2CvDepth<int>(depth) + ((nChannels - 1) << CV_CN_SHIFT));
283 #if IMAGE_ALLOC_PERFLOG
284 alloc_tims.leave(sLog.c_str());
288 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
299 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
310 #ifdef HAVE_OPENCV_IMGCODECS
312 MRPT_TODO(
"add flag to reuse current img buffer");
314 m_impl->img = cv::imread(fileName,
static_cast<cv::ImreadModes
>(
isColor));
317 if (!newImg)
return false;
318 m_impl->img = cv::cvarrToMat(newImg);
320 if (
m_impl->img.empty())
return false;
324 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
336 #ifdef HAVE_OPENCV_IMGCODECS
337 const std::vector<int>
params = {cv::IMWRITE_JPEG_QUALITY, jpeg_quality};
340 int p[3] = {CV_IMWRITE_JPEG_QUALITY, jpeg_quality, 0};
341 _IplImage ipl =
m_impl->img;
342 return (0 != cvSaveImage(fileName.c_str(), &ipl, p));
345 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
357 cv::cvarrToMat(iplImage, c ==
DEEP_COPY ?
true :
false );
359 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
365 unsigned int width,
unsigned int height,
bool color,
366 unsigned char* rawpixels,
bool swapRedBlue)
374 auto* imgData =
m_impl->img.data;
375 const auto imgWidthStep =
m_impl->img.step[0];
377 if (color && swapRedBlue)
380 unsigned char* ptr_src = rawpixels;
381 auto* ptr_dest = imgData;
382 const int bytes_per_row_out = imgWidthStep;
384 for (
int h = height; h--;)
386 for (
unsigned int i = 0; i < width;
387 i++, ptr_src += 3, ptr_dest += 3)
389 unsigned char t0 = ptr_src[0], t1 = ptr_src[1], t2 = ptr_src[2];
394 ptr_dest += bytes_per_row_out - width * 3;
400 static_cast<size_t>(
m_impl->img.cols *
m_impl->img.channels()))
408 unsigned char* ptr_src = rawpixels;
409 auto* ptr_dest = imgData;
410 int bytes_per_row = width * (color ? 3 : 1);
411 int bytes_per_row_out = imgWidthStep;
412 for (
unsigned int y = 0; y < height; y++)
414 memcpy(ptr_dest, ptr_src, bytes_per_row);
415 ptr_src += bytes_per_row;
416 ptr_dest += bytes_per_row_out;
421 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
427 unsigned int ucol,
unsigned int urow,
unsigned int uchannel)
const
431 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
436 const auto col =
static_cast<int>(ucol);
437 const auto row =
static_cast<int>(urow);
438 const auto channel =
static_cast<int>(uchannel);
440 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
442 if (row >=
m_impl->img.rows || col >=
m_impl->img.cols ||
443 channel >=
m_impl->img.channels())
446 "Pixel coordinates/channel out of bounds: row=%u/%u col=%u/%u "
453 (&
m_impl->img.at<uint8_t>(row,
m_impl->img.channels() * col)) + channel;
454 return const_cast<unsigned char*
>(p);
455 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
469 (&
m_impl->img.at<uint8_t>(row,
m_impl->img.channels() * col)) + channel;
470 return const_cast<uint8_t*
>(p);
477 unsigned int col,
unsigned int row, uint8_t channel)
const
509 const bool hasColor =
m_impl->img.empty() ? false :
isColor();
514 const int32_t width =
m_impl->img.cols;
515 const int32_t height =
m_impl->img.rows;
522 uint32_t imageSize = height *
m_impl->img.step[0];
524 int32_t depth =
m_impl->img.depth();
526 out << width << height << origin << imageSize
533 bool imageStoredAsZip =
false;
535 out << imageStoredAsZip;
537 if (imageSize > 0 &&
m_impl->img.data !=
nullptr)
538 out.WriteBuffer(
m_impl->img.data, imageSize);
551 out << width << height;
553 if (width >= 1 && height >= 1)
570 const int32_t neg_width = -width;
571 const int32_t neg_height = -height;
573 out << neg_width << neg_height;
576 const auto bytes_per_row = width * 3;
578 out.WriteBuffer(
m_impl->img.data, bytes_per_row * height);
596 "[CImage] Cannot deserialize image since MRPT has been "
597 "compiled without OpenCV");
614 uint32_t width, height, nChannels, imgLength;
615 uint8_t originTopLeft;
617 in >> width >> height >> nChannels >> originTopLeft >> imgLength;
628 std::vector<uint8_t> buf(nBytes);
666 int32_t width, height, origin, imageSize;
667 in >> width >> height >> origin >> imageSize;
676 static_cast<uint32_t
>(width),
677 static_cast<uint32_t
>(height),
CH_GRAY, depth);
679 static_cast<uint32_t
>(imageSize),
680 static_cast<uint32_t
>(height) *
m_impl->img.step[0]);
690 bool imageIsZIP =
true;
694 if (version == 4 && imageSize <= 16 * 1024)
708 "ZIP image deserialization not supported "
721 bool loadJPEG =
true;
725 int32_t width, height;
726 in >> width >> height;
728 if (width >= 1 && height >= 1)
736 if (width < 0 && height < 0)
739 const int32_t real_w = -width;
740 const int32_t real_h = -height;
745 const size_t bytes_per_row = img.cols * 3;
746 for (
int y = 0; y < img.rows; y++)
749 img.ptr<
void>(y), bytes_per_row);
750 if (nRead != bytes_per_row)
752 "Error: Truncated data stream "
753 "while parsing raw image?");
771 std::vector<uint8_t> buf(nBytes);
835 const int chCount =
m_impl->img.channels();
838 const std::array<const char*, 4> orderNames = {
"GRAY",
"",
"BGR",
"BGRA"};
839 return std::string(orderNames.at(chCount - 1));
849 return m_impl->img.step[0];
869 return m_impl->img.channels() == 3;
900 unsigned int col,
unsigned int row,
unsigned int channel)
const
904 return (*(*
this)(col, row, channel)) / 255.0f;
913 unsigned char* pixels = (*this)(col, row, 0);
914 return (pixels[0] * 0.3f + pixels[1] * 0.59f + pixels[2] * 0.11f) /
920 return (*(*
this)(col, row, 0 )) / 255.0f;
933 for (x = 0; x < cx; x++)
934 for (y = 0; y < cy; y++) maxPixel = max(maxPixel,
getAsFloat(x, y));
950 if (dest.size() != src.size() || dest.type() != src.type())
951 dest = cv::Mat(src.rows, src.cols, CV_8UC1);
954 #if MRPT_ARCH_INTEL_COMPATIBLE
955 if ((src.step[0] & 0x0f) == 0 && (dest.step[0] & 0x0f) == 0 &&
959 src.ptr<uint8_t>(), dest.ptr<uint8_t>(), src.cols, src.rows,
960 src.step[0], dest.step[0]);
966 cv::cvtColor(src, dest, CV_BGR2GRAY);
976 if (
m_impl->img.channels() == 1)
984 cv::Mat src =
m_impl->img;
986 if (src.data == ret.
m_impl->img.data) src = src.clone();
991 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
1001 const int w = img.cols, h = img.rows;
1005 auto& img_out =
out.m_impl->img;
1008 #if MRPT_ARCH_INTEL_COMPATIBLE
1013 img.data, img_out.data, w, h, img.step[0], img_out.step[0]);
1022 img.data, img_out.data, w, h, img.step[0], img_out.step[0]);
1028 img.data, img_out.data, w, h, img.step[0], img_out.step[0]);
1039 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
1051 unsigned int width,
unsigned int height,
unsigned int bytesPerRow,
1052 unsigned char* red,
unsigned char* green,
unsigned char* blue)
1060 for (
unsigned int y = 0; y < height; y++)
1063 auto* dest =
m_impl->img.ptr<uint8_t>(y);
1066 unsigned char* srcR = red + bytesPerRow * y;
1067 unsigned char* srcG = green + bytesPerRow * y;
1068 unsigned char* srcB = blue + bytesPerRow * y;
1070 for (
unsigned int x = 0; x < width; x++)
1072 *(dest++) = *(srcB++);
1073 *(dest++) = *(srcG++);
1074 *(dest++) = *(srcR++);
1086 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
1095 if (x >= 0 && y >= 0 && y < img.rows && x < img.cols)
1098 if (img.channels() == 1)
1100 img.ptr<uint8_t>(y)[x] =
static_cast<uint8_t
>(color);
1104 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
1107 auto* dest = &img.ptr<uint8_t>(y)[3 * x];
1108 const auto* src =
reinterpret_cast<uint8_t*
>(&color);
1116 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
1125 unsigned int width, [[maybe_unused]]
TPenStyle penStyle)
1131 m_impl->img, cv::Point(x0, y0), cv::Point(x1, y1),
1132 CV_RGB(color.
R, color.
G, color.
B),
static_cast<int>(width));
1143 m_impl->img, cv::Point(x, y), radius, CV_RGB(color.
R, color.
G, color.
B),
1144 static_cast<int>(width));
1155 cv::Mat dest =
m_impl->img(roi);
1156 img.
m_impl->img.copyTo(dest);
1161 const CImage& patch,
const unsigned int col_,
const unsigned int row_)
1165 const auto& src =
m_impl->img;
1166 auto& dest = patch.
m_impl->img;
1168 src(cv::Rect(col_, row_, dest.cols, dest.rows)).copyTo(dest);
1173 CImage& patch,
const unsigned int col_,
const unsigned int row_,
1174 const unsigned int col_num,
const unsigned int row_num)
const
1178 const auto& src =
m_impl->img;
1179 auto& dest = patch.
m_impl->img;
1181 src(cv::Rect(col_, row_, col_num, row_num)).copyTo(dest);
1186 const CImage& img2,
int width_init,
int height_init)
const
1193 THROW_EXCEPTION(
"Correlation Error!, image to correlate out of bounds");
1196 float syy = 0.0f, sxy = 0.0f, sxx = 0.0f, m1 = 0.0f, m2 = 0.0f,
1200 for (
size_t i = 0; i < img2.
getHeight(); i++)
1202 for (
size_t j = 0; j < img2.
getWidth(); j++)
1215 for (
size_t i = 0; i < img2.
getHeight(); i++)
1217 for (
size_t j = 0; j < img2.
getWidth(); j++)
1219 x1 = *(*this)(j + width_init, i + height_init) -
1222 x2 = *img2(j, i) - m2;
1230 return sxy / sqrt(sxx * syy);
1245 CMatrixFloat& outMatrix,
bool doResize,
int x_min,
int y_min,
int x_max,
1246 int y_max,
bool normalize_01)
const
1252 const auto& img =
m_impl->img;
1255 if (x_max == -1) x_max = img.cols - 1;
1256 if (y_max == -1) y_max = img.rows - 1;
1258 ASSERT_(x_min >= 0 && x_min < img.cols && x_min < x_max);
1259 ASSERT_(y_min >= 0 && y_min < img.rows && y_min < y_max);
1261 int lx = (x_max - x_min + 1);
1262 int ly = (y_max - y_min + 1);
1264 if (doResize || outMatrix.
rows() < ly || outMatrix.
cols() < lx)
1265 outMatrix.
setSize(y_max - y_min + 1, x_max - x_min + 1);
1267 const bool is_color =
isColor();
1270 for (
int y = 0; y < ly; y++)
1272 const uint8_t* pixels = ptr<uint8_t>(x_min, y_min + y);
1273 for (
int x = 0; x < lx; x++)
1278 aux = *pixels++ * 0.3f;
1279 aux += *pixels++ * 0.59f;
1280 aux += *pixels++ * 0.11f;
1289 if (normalize_01) outMatrix *= (1.0f / 255);
1296 CMatrix_u8& outMatrix,
bool doResize,
int x_min,
int y_min,
int x_max,
1303 const auto& img =
m_impl->img;
1306 if (x_max == -1) x_max = img.cols - 1;
1307 if (y_max == -1) y_max = img.rows - 1;
1309 ASSERT_(x_min >= 0 && x_min < img.cols && x_min < x_max);
1310 ASSERT_(y_min >= 0 && y_min < img.rows && y_min < y_max);
1312 int lx = (x_max - x_min + 1);
1313 int ly = (y_max - y_min + 1);
1315 if (doResize || outMatrix.
rows() < ly || outMatrix.
cols() < lx)
1316 outMatrix.
setSize(y_max - y_min + 1, x_max - x_min + 1);
1318 const bool is_color =
isColor();
1321 for (
int y = 0; y < ly; y++)
1323 const uint8_t* pixels = ptr<uint8_t>(x_min, y_min + y);
1324 for (
int x = 0; x < lx; x++)
1328 unsigned int aux = *pixels++ * 3000;
1329 aux += *pixels++ * 5900;
1330 aux += *pixels++ * 1100;
1331 outMatrix.
coeffRef(y, x) =
static_cast<uint8_t
>(aux / 1000);
1335 outMatrix.
coeffRef(y, x) = (*pixels++);
1352 const auto& img =
m_impl->img;
1355 if (x_max == -1) x_max = img.cols - 1;
1356 if (y_max == -1) y_max = img.rows - 1;
1358 ASSERT_(x_min >= 0 && x_min < img.cols && x_min < x_max);
1359 ASSERT_(y_min >= 0 && y_min < img.rows && y_min < y_max);
1361 int lx = (x_max - x_min + 1);
1362 int ly = (y_max - y_min + 1);
1364 if (doResize ||
R.rows() < ly ||
R.cols() < lx)
R.setSize(ly, lx);
1365 if (doResize ||
G.rows() < ly ||
G.cols() < lx)
G.setSize(ly, lx);
1368 const bool is_color =
isColor();
1369 for (
int y = 0; y < ly; y++)
1371 const uint8_t* pixels = ptr<uint8_t>(x_min, y_min + y);
1372 for (
int x = 0; x < lx; x++)
1376 R.coeffRef(y, x) =
u8tof(*pixels++);
1377 G.coeffRef(y, x) =
u8tof(*pixels++);
1382 R.coeffRef(y, x) =
G.coeffRef(y, x) = B.
coeffRef(y, x) =
1401 const auto& img =
m_impl->img;
1404 if (x_max == -1) x_max = img.cols - 1;
1405 if (y_max == -1) y_max = img.rows - 1;
1407 ASSERT_(x_min >= 0 && x_min < img.cols && x_min < x_max);
1408 ASSERT_(y_min >= 0 && y_min < img.rows && y_min < y_max);
1410 int lx = (x_max - x_min + 1);
1411 int ly = (y_max - y_min + 1);
1413 if (doResize ||
R.rows() < ly ||
R.cols() < lx)
R.setSize(ly, lx);
1414 if (doResize ||
G.rows() < ly ||
G.cols() < lx)
G.setSize(ly, lx);
1417 const bool is_color =
isColor();
1418 for (
int y = 0; y < ly; y++)
1420 const uint8_t* pixels = ptr<uint8_t>(x_min, y_min + y);
1421 for (
int x = 0; x < lx; x++)
1425 R.coeffRef(y, x) = *pixels++;
1426 G.coeffRef(y, x) = *pixels++;
1431 R.coeffRef(y, x) =
G.coeffRef(y, x) = B.
coeffRef(y, x) =
1443 int v_search_ini,
int u_search_size,
int v_search_size,
float biasThisImg,
1444 float biasInImg)
const
1451 if (u_search_ini == -1) u_search_ini = 0;
1452 if (v_search_ini == -1) v_search_ini = 0;
1453 if (u_search_size == -1) u_search_size =
static_cast<int>(
getWidth());
1454 if (v_search_size == -1) v_search_size =
static_cast<int>(
getHeight());
1456 int u_search_end = u_search_ini + u_search_size - 1;
1457 int v_search_end = v_search_ini + v_search_size - 1;
1465 std::max(
static_cast<size_t>(u_search_size), in_img.
getWidth());
1467 std::max(
static_cast<size_t>(v_search_size), in_img.
getHeight());
1468 size_t lx = mrpt::round2up<size_t>(actual_lx);
1469 size_t ly = mrpt::round2up<size_t>(actual_ly);
1477 i2.
fill(biasThisImg);
1481 i2,
false, u_search_ini, v_search_ini, u_search_ini + u_search_size - 1,
1482 v_search_ini + v_search_size - 1);
1490 CMatrixF I1_R, I1_I, I2_R, I2_I, ZEROS(ly, lx);
1495 for (y = 0; y < ly; y++)
1496 for (x = 0; x < lx; x++)
1498 float r1 = I1_R(y, x);
1499 float r2 = I2_R(y, x);
1501 float ii1 = I1_I(y, x);
1502 float ii2 = I2_I(y, x);
1505 I2_R(y, x) = (r1 * r2 + ii1 * ii2) / den;
1506 I2_I(y, x) = (ii2 * r1 - r2 * ii1) / den;
1513 out_corr.
setSize(actual_ly, actual_lx);
1514 for (y = 0; y < actual_ly; y++)
1515 for (x = 0; x < actual_lx; x++)
1516 out_corr(y, x) = sqrt(
square(res_R(y, x)) +
square(res_I(y, x)));
1527 const auto& img =
m_impl->img;
1530 const auto matrix_lx = outMatrix.
cols();
1531 const auto matrix_ly = outMatrix.
rows();
1538 unsigned char* min_pixels = (*this)(0, y % img.rows, 0);
1539 unsigned char* max_pixels = min_pixels + img.cols * 3;
1540 unsigned char* pixels = min_pixels;
1544 aux = *pixels++ * 0.30f;
1545 aux += *pixels++ * 0.59f;
1546 aux += *pixels++ * 0.11f;
1547 outMatrix(y, x) = aux;
1548 if (pixels >= max_pixels) pixels = min_pixels;
1556 unsigned char* min_pixels = (*this)(0, y % img.rows, 0);
1557 unsigned char* max_pixels = min_pixels + img.
cols;
1558 unsigned char* pixels = min_pixels;
1561 outMatrix(y, x) = *pixels++;
1562 if (pixels >= max_pixels) pixels = min_pixels;
1580 m_externalFile = fileName;
1581 m_imgIsExternalStorage =
true;
1594 if (!
m_impl->img.empty())
return;
1615 "Error loading externally-stored image from: %s",
1621 "Trying to access uninitialized image in a non "
1622 "externally-stored "
1669 cv::cvtColor(
m_impl->img,
m_impl->img, cv::COLOR_RGB2BGR);
1678 auto& srcImg =
m_impl->img;
1679 cv::Mat outImg(srcImg.rows, srcImg.cols, srcImg.type());
1681 auto mapXm =
static_cast<cv::Mat*
>(mapX);
1682 auto mapYm =
static_cast<cv::Mat*
>(mapX);
1684 cv::remap(srcImg, outImg, *mapXm, *mapYm, cv::INTER_CUBIC);
1699 "In-place undistort() not supported");
1701 auto& srcImg =
const_cast<cv::Mat&
>(
m_impl->img);
1706 const auto& dist = cameraParams.
dist;
1708 cv::Mat distM(1, dist.size(), CV_64F,
const_cast<double*
>(&dist[0]));
1709 cv::Mat inMat(3, 3, CV_64F);
1711 for (
int i = 0; i < 3; i++)
1712 for (
int j = 0; j < 3; j++) inMat.at<
double>(i, j) = intrMat(i, j);
1714 cv::undistort(srcImg, out_img.
m_impl->img, inMat, distM);
1723 auto srcImg =
const_cast<cv::Mat&
>(
m_impl->img);
1724 if (
this == &out_img)
1725 srcImg = srcImg.clone();
1729 cv::medianBlur(srcImg, out_img.
m_impl->img, W);
1737 auto srcImg =
const_cast<cv::Mat&
>(
m_impl->img);
1738 if (
this == &out_img)
1739 srcImg = srcImg.clone();
1743 cv::GaussianBlur(srcImg, out_img.
m_impl->img, cv::Size(W, H), sigma);
1748 CImage& out_img,
unsigned int width,
unsigned int height,
1754 auto srcImg =
m_impl->img;
1756 if (out_img.
m_impl->img.data == srcImg.data) srcImg = srcImg.clone();
1761 out_img.
m_impl->img = srcImg;
1768 srcImg, out_img.
m_impl->img, out_img.
m_impl->img.size(), 0, 0,
1774 CImage& out_img,
double ang,
unsigned int cx,
unsigned int cy,
1780 auto srcImg =
m_impl->img;
1782 if (out_img.
m_impl->img.data == srcImg.data) srcImg = srcImg.clone();
1790 double m[2 * 3] = {scale * cos(ang), -scale * sin(ang), 1.0 * cx,
1791 scale * sin(ang), scale * cos(ang), 1.0 * cy};
1792 cv::Mat M(2, 3, CV_64F, m);
1794 double dx = (srcImg.cols - 1) * 0.5;
1795 double dy = (srcImg.rows - 1) * 0.5;
1796 m[2] -= m[0] * dx + m[1] * dy;
1797 m[5] -= m[3] * dx + m[4] * dy;
1800 srcImg, out_img.
m_impl->img, M, out_img.
m_impl->img.size(),
1801 cv::INTER_LINEAR + cv::WARP_INVERSE_MAP, cv::BORDER_REPLICATE);
1806 std::vector<TPixelCoordf>& cornerCoords,
unsigned int check_size_x,
1807 unsigned int check_size_y,
unsigned int lines_width,
unsigned int r)
1815 unsigned int x, y, i;
1816 cv::Point prev_pt = cvPoint(0, 0);
1817 const int line_max = 8;
1820 line_colors[0] = CV_RGB(255, 0, 0);
1821 line_colors[1] = CV_RGB(255, 128, 0);
1822 line_colors[2] = CV_RGB(255, 128, 0);
1823 line_colors[3] = CV_RGB(200, 200, 0);
1824 line_colors[4] = CV_RGB(0, 255, 0);
1825 line_colors[5] = CV_RGB(0, 200, 200);
1826 line_colors[6] = CV_RGB(0, 0, 255);
1827 line_colors[7] = CV_RGB(255, 0, 255);
1833 const auto color = line_colors[y % line_max];
1837 pt.x = cvRound(cornerCoords[i].x);
1838 pt.y = cvRound(cornerCoords[i].y);
1840 if (i != 0) cv::line(img, prev_pt, pt, color, lines_width);
1843 img, cvPoint(pt.x - r, pt.y - r), cvPoint(pt.x + r, pt.y + r),
1844 color, lines_width);
1846 img, cvPoint(pt.x - r, pt.y + r), cvPoint(pt.x + r, pt.y - r),
1847 color, lines_width);
1849 if (r > 0) cv::circle(img, pt, r + 1, color);
1854 if (i == 0 || i == cornerCoords.size() - 1)
1879 if (&ret !=
this) ret = *
this;
1883 auto srcImg =
m_impl->img;
1885 if (srcImg.data == ret.
m_impl->img.data) srcImg = srcImg.clone();
1889 cv::cvtColor(srcImg, ret.
m_impl->img, cv::COLOR_GRAY2BGR);
1899 ASSERT_(im1.type() == im2.type());
1903 im1.copyTo(img(cv::Rect(0, 0, im1.cols, im1.rows)));
1904 im2.copyTo(img(cv::Rect(im1.cols, 0, im2.cols, im2.rows)));
1912 auto srcImg =
m_impl->img;
1913 if (
this != &out_img)
1915 auto outImg = out_img.
m_impl->img;
1917 if (srcImg.channels() == 1)
1918 cv::equalizeHist(srcImg, outImg);
1926 #if defined(__GNUC__)
1927 #define MRPT_DISABLE_FULL_OPTIMIZATION __attribute__((optimize("O1")))
1929 #define MRPT_DISABLE_FULL_OPTIMIZATION
1932 template <
unsigned int HALF_WIN_SIZE>
1934 const uint8_t* in,
const int widthStep,
unsigned int x,
unsigned int y,
1935 int32_t& _gxx, int32_t& _gyy, int32_t& _gxy)
1937 const auto min_x = x - HALF_WIN_SIZE;
1938 const auto min_y = y - HALF_WIN_SIZE;
1944 const unsigned int WIN_SIZE = 1 + 2 * HALF_WIN_SIZE;
1946 unsigned int yy = min_y;
1947 for (
unsigned int iy = WIN_SIZE; iy; --iy, ++yy)
1949 const uint8_t* ptr = in + widthStep * yy + min_x;
1950 unsigned int xx = min_x;
1951 for (
unsigned int ix = WIN_SIZE; ix; --ix, ++xx, ++ptr)
1954 static_cast<int32_t
>(ptr[+1]) -
static_cast<int32_t
>(ptr[-1]);
1955 const int32_t dy =
static_cast<int32_t
>(ptr[+widthStep]) -
1956 static_cast<int32_t
>(ptr[-widthStep]);
1968 const unsigned int x,
const unsigned int y,
1969 const unsigned int half_window_size)
const
1973 const auto& im1 =
m_impl->img;
1974 const auto img_w =
static_cast<unsigned int>(im1.cols),
1975 img_h =
static_cast<unsigned int>(im1.rows);
1976 const int widthStep = im1.step[0];
1979 const unsigned int min_x = x - half_window_size;
1980 const unsigned int max_x = x + half_window_size;
1981 const unsigned int min_y = y - half_window_size;
1982 const unsigned int max_y = y + half_window_size;
1987 min_x < img_w && max_x < img_w && min_y < img_h && max_y < img_h,
1988 "Window is out of image bounds");
1996 const auto* img_data = im1.ptr<uint8_t>(0);
1997 switch (half_window_size)
2000 image_KLT_response_template<2>(
2001 img_data, widthStep, x, y, gxx, gyy, gxy);
2004 image_KLT_response_template<3>(
2005 img_data, widthStep, x, y, gxx, gyy, gxy);
2008 image_KLT_response_template<4>(
2009 img_data, widthStep, x, y, gxx, gyy, gxy);
2012 image_KLT_response_template<5>(
2013 img_data, widthStep, x, y, gxx, gyy, gxy);
2016 image_KLT_response_template<6>(
2017 img_data, widthStep, x, y, gxx, gyy, gxy);
2020 image_KLT_response_template<7>(
2021 img_data, widthStep, x, y, gxx, gyy, gxy);
2024 image_KLT_response_template<8>(
2025 img_data, widthStep, x, y, gxx, gyy, gxy);
2028 image_KLT_response_template<9>(
2029 img_data, widthStep, x, y, gxx, gyy, gxy);
2032 image_KLT_response_template<10>(
2033 img_data, widthStep, x, y, gxx, gyy, gxy);
2036 image_KLT_response_template<11>(
2037 img_data, widthStep, x, y, gxx, gyy, gxy);
2040 image_KLT_response_template<12>(
2041 img_data, widthStep, x, y, gxx, gyy, gxy);
2044 image_KLT_response_template<13>(
2045 img_data, widthStep, x, y, gxx, gyy, gxy);
2048 image_KLT_response_template<14>(
2049 img_data, widthStep, x, y, gxx, gyy, gxy);
2052 image_KLT_response_template<15>(
2053 img_data, widthStep, x, y, gxx, gyy, gxy);
2056 image_KLT_response_template<16>(
2057 img_data, widthStep, x, y, gxx, gyy, gxy);
2060 image_KLT_response_template<32>(
2061 img_data, widthStep, x, y, gxx, gyy, gxy);
2065 for (
unsigned int yy = min_y; yy <= max_y; yy++)
2067 const uint8_t* p = img_data + widthStep * yy + min_x;
2068 for (
unsigned int xx = min_x; xx <= max_x; xx++)
2070 const int32_t dx = p[+1] - p[-1];
2071 const int32_t dy = p[+widthStep] - p[-widthStep];
2080 const float K = 0.5f / ((max_y - min_y + 1) * (max_x - min_x + 1));
2081 const float Gxx = gxx * K;
2082 const float Gxy = gxy * K;
2083 const float Gyy = gyy * K;
2090 const float t = Gxx + Gyy;
2091 const float de = Gxx * Gyy - Gxy * Gxy;
2093 return 0.5f * (t - std::sqrt(t * t - 4.0f * de));
2108 std::fstream stream;
2109 stream.open(fileName.c_str(), std::fstream::in | std::fstream::binary);
2110 if (!stream.is_open())
2112 std::cerr <<
"[CImage::loadTGA] Couldn't open file '" << fileName
2119 stream.seekg(0, std::ios_base::beg);
2122 char dumpBuffer[12];
2123 char trueColorHeader[] =
"\0\0\2\0\0\0\0\0\0\0\0\0";
2124 stream.read(dumpBuffer, 12);
2125 if (memcmp(dumpBuffer, trueColorHeader, 12) != 0)
2127 std::cerr <<
"[CImage::loadTGA] Unsupported format or invalid file.\n";
2131 unsigned short width, height;
2134 stream.read((
char*)&width, 2);
2135 stream.read((
char*)&height, 2);
2139 std::cerr <<
"[CImage::loadTGA] Only 32 bpp format supported!\n";
2144 desc = stream.get();
2145 if (desc != 8 && desc != 32)
2147 std::cerr <<
"[CImage::loadTGA] Unsupported format or invalid file.\n";
2150 const bool origin_is_low_corner = (desc == 8);
2153 std::vector<uint8_t> bytes(width * height * 4);
2154 stream.read((
char*)&bytes[0], width * height * 4);
2162 for (
int r = 0; r < height; r++)
2164 const auto actual_row = origin_is_low_corner ? (height - 1 - r) : r;
2165 auto& img = out_RGB.
m_impl->img;
2166 auto data = img.ptr<uint8_t>(actual_row);
2168 auto& img_alpha = out_alpha.
m_impl->img;
2169 auto data_alpha = img_alpha.ptr<uint8_t>(actual_row);
2171 for (
unsigned int c = 0; c < width; c++)
2173 *
data++ = bytes[idx++];
2174 *
data++ = bytes[idx++];
2175 *
data++ = bytes[idx++];
2176 *data_alpha++ = bytes[idx++];
2183 #endif // MRPT_HAS_OPENCV
2191 #if MRPT_OPENCV_VERSION_NUM < 0x300
2193 *dest = cvIplImage(
m_impl->img);
2202 o <<
"(" << p.
x <<
"," << p.
y <<
")";
2207 o <<
"(" << p.
x <<
"," << p.
y <<
")";