29 #include <mrpt/3rdparty/do_opencv_includes.h>
34 #include <mexplus/mxarray.h>
72 : std::runtime_error(s)
83 #define IMAGE_ALLOC_PERFLOG 0
85 #if IMAGE_ALLOC_PERFLOG
104 template <
typename RET = u
int32_t>
119 return std::numeric_limits<RET>::max();
121 template <
typename RET = u
int32_t>
136 return std::numeric_limits<RET>::max();
156 #endif // MRPT_HAS_OPENCV
163 unsigned int width,
unsigned int height,
TImageChannels nChannels)
167 resize(width, height, nChannels);
189 m_impl->img = img.clone();
199 CImage(img.m_impl->img, copy_type)
213 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
221 out_img =
m_impl->img.clone();
233 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
243 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
262 if (
static_cast<unsigned>(ipl.width) == width &&
263 static_cast<unsigned>(ipl.height) == height &&
264 ipl.nChannels == nChannels &&
272 #if IMAGE_ALLOC_PERFLOG
273 const std::string sLog =
mrpt::format(
"cvCreateImage %ux%u", width, height);
274 alloc_tims.enter(sLog.c_str());
281 static_cast<int>(height),
static_cast<int>(width),
282 pixelDepth2CvDepth<int>(depth) + ((nChannels - 1) << CV_CN_SHIFT));
284 #if IMAGE_ALLOC_PERFLOG
285 alloc_tims.leave(sLog.c_str());
289 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
300 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
311 #ifdef HAVE_OPENCV_IMGCODECS
313 MRPT_TODO(
"add flag to reuse current img buffer");
315 m_impl->img = cv::imread(fileName,
static_cast<cv::ImreadModes
>(
isColor));
318 if (!newImg)
return false;
319 m_impl->img = cv::cvarrToMat(newImg);
321 if (
m_impl->img.empty())
return false;
325 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
337 #ifdef HAVE_OPENCV_IMGCODECS
338 const std::vector<int>
params = {cv::IMWRITE_JPEG_QUALITY, jpeg_quality};
341 int p[3] = {CV_IMWRITE_JPEG_QUALITY, jpeg_quality, 0};
342 _IplImage ipl =
m_impl->img;
343 return (0 != cvSaveImage(fileName.c_str(), &ipl, p));
346 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
358 cv::cvarrToMat(iplImage, c ==
DEEP_COPY ?
true :
false );
360 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
366 unsigned int width,
unsigned int height,
bool color,
367 unsigned char* rawpixels,
bool swapRedBlue)
378 if (color && swapRedBlue)
381 unsigned char* ptr_src = rawpixels;
382 auto* ptr_dest =
reinterpret_cast<unsigned char*
>(img->imageData);
383 const int bytes_per_row_out = img->widthStep;
385 for (
int h = height; h--;)
387 for (
unsigned int i = 0; i < width;
388 i++, ptr_src += 3, ptr_dest += 3)
390 unsigned char t0 = ptr_src[0], t1 = ptr_src[1], t2 = ptr_src[2];
395 ptr_dest += bytes_per_row_out - width * 3;
400 if (img->widthStep == img->width * img->nChannels)
403 memcpy(img->imageData, rawpixels, img->imageSize);
408 unsigned char* ptr_src = rawpixels;
409 auto* ptr_dest =
reinterpret_cast<unsigned char*
>(img->imageData);
410 int bytes_per_row = width * (color ? 3 : 1);
411 int bytes_per_row_out = img->widthStep;
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);
833 return std::string(ipl.channelSeq);
843 return m_impl->img.step[0];
863 return m_impl->img.channels() == 3;
894 unsigned int col,
unsigned int row,
unsigned int channel)
const
898 return (*(*
this)(col, row, channel)) / 255.0f;
907 unsigned char* pixels = (*this)(col, row, 0);
908 return (pixels[0] * 0.3f + pixels[1] * 0.59f + pixels[2] * 0.11f) /
914 return (*(*
this)(col, row, 0 )) / 255.0f;
927 for (x = 0; x < cx; x++)
928 for (y = 0; y < cy; y++) maxPixel = max(maxPixel,
getAsFloat(x, y));
944 if (dest.size() != src.size() || dest.type() != src.type())
945 dest = cv::Mat(src.rows, src.cols, CV_8UC1);
948 #if MRPT_ARCH_INTEL_COMPATIBLE
949 if ((src.step[0] & 0x0f) == 0 && (dest.step[0] & 0x0f) == 0 &&
953 src.ptr<uint8_t>(), dest.ptr<uint8_t>(), src.cols, src.rows,
954 src.step[0], dest.step[0]);
960 cv::cvtColor(src, dest, CV_BGR2GRAY);
970 if (
m_impl->img.channels() == 1)
978 cv::Mat src =
m_impl->img;
980 if (src.data == ret.
m_impl->img.data) src = src.clone();
985 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
995 const int w = img.cols, h = img.rows;
999 auto& img_out =
out.m_impl->img;
1002 #if MRPT_ARCH_INTEL_COMPATIBLE
1007 img.data, img_out.data, w, h, img.step[0], img_out.step[0]);
1016 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]);
1033 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
1045 unsigned int width,
unsigned int height,
unsigned int bytesPerRow,
1046 unsigned char* red,
unsigned char* green,
unsigned char* blue)
1054 for (
unsigned int y = 0; y < height; y++)
1057 auto* dest =
m_impl->img.ptr<uint8_t>(y);
1060 unsigned char* srcR = red + bytesPerRow * y;
1061 unsigned char* srcG = green + bytesPerRow * y;
1062 unsigned char* srcB = blue + bytesPerRow * y;
1064 for (
unsigned int x = 0; x < width; x++)
1066 *(dest++) = *(srcB++);
1067 *(dest++) = *(srcG++);
1068 *(dest++) = *(srcR++);
1080 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
1089 if (x >= 0 && y >= 0 && y < img.rows && x < img.cols)
1092 if (img.channels() == 1)
1094 img.ptr<uint8_t>(y)[x] =
static_cast<uint8_t
>(color);
1098 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
1101 auto* dest = &img.ptr<uint8_t>(y)[3 * x];
1102 const auto* src =
reinterpret_cast<uint8_t*
>(&color);
1110 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
1119 unsigned int width, [[maybe_unused]]
TPenStyle penStyle)
1125 m_impl->img, cv::Point(x0, y0), cv::Point(x1, y1),
1126 CV_RGB(color.
R, color.
G, color.
B),
static_cast<int>(width));
1137 m_impl->img, cv::Point(x, y), radius, CV_RGB(color.
R, color.
G, color.
B),
1138 static_cast<int>(width));
1149 cv::Mat dest =
m_impl->img(roi);
1150 img.
m_impl->img.copyTo(dest);
1155 const CImage& patch,
const unsigned int col_,
const unsigned int row_)
1159 const auto& src =
m_impl->img;
1160 auto& dest = patch.
m_impl->img;
1162 src(cv::Rect(col_, row_, dest.cols, dest.rows)).copyTo(dest);
1167 CImage& patch,
const unsigned int col_,
const unsigned int row_,
1168 const unsigned int col_num,
const unsigned int row_num)
const
1172 const auto& src =
m_impl->img;
1173 auto& dest = patch.
m_impl->img;
1175 src(cv::Rect(col_, row_, col_num, row_num)).copyTo(dest);
1180 const CImage& img2,
int width_init,
int height_init)
const
1187 THROW_EXCEPTION(
"Correlation Error!, image to correlate out of bounds");
1190 float syy = 0.0f, sxy = 0.0f, sxx = 0.0f, m1 = 0.0f, m2 = 0.0f,
1194 for (
size_t i = 0; i < img2.
getHeight(); i++)
1196 for (
size_t j = 0; j < img2.
getWidth(); j++)
1209 for (
size_t i = 0; i < img2.
getHeight(); i++)
1211 for (
size_t j = 0; j < img2.
getWidth(); j++)
1213 x1 = *(*this)(j + width_init, i + height_init) -
1216 x2 = *img2(j, i) - m2;
1224 return sxy / sqrt(sxx * syy);
1239 CMatrixFloat& outMatrix,
bool doResize,
int x_min,
int y_min,
int x_max,
1240 int y_max,
bool normalize_01)
const
1246 const auto& img =
m_impl->img;
1249 if (x_max == -1) x_max = img.cols - 1;
1250 if (y_max == -1) y_max = img.rows - 1;
1252 ASSERT_(x_min >= 0 && x_min < img.cols && x_min < x_max);
1253 ASSERT_(y_min >= 0 && y_min < img.rows && y_min < y_max);
1255 int lx = (x_max - x_min + 1);
1256 int ly = (y_max - y_min + 1);
1258 if (doResize || outMatrix.
rows() < ly || outMatrix.
cols() < lx)
1259 outMatrix.
setSize(y_max - y_min + 1, x_max - x_min + 1);
1261 const bool is_color =
isColor();
1264 for (
int y = 0; y < ly; y++)
1266 const uint8_t* pixels = ptr<uint8_t>(x_min, y_min + y);
1267 for (
int x = 0; x < lx; x++)
1272 aux = *pixels++ * 0.3f;
1273 aux += *pixels++ * 0.59f;
1274 aux += *pixels++ * 0.11f;
1283 if (normalize_01) outMatrix *= (1.0f / 255);
1290 CMatrix_u8& outMatrix,
bool doResize,
int x_min,
int y_min,
int x_max,
1297 const auto& img =
m_impl->img;
1300 if (x_max == -1) x_max = img.cols - 1;
1301 if (y_max == -1) y_max = img.rows - 1;
1303 ASSERT_(x_min >= 0 && x_min < img.cols && x_min < x_max);
1304 ASSERT_(y_min >= 0 && y_min < img.rows && y_min < y_max);
1306 int lx = (x_max - x_min + 1);
1307 int ly = (y_max - y_min + 1);
1309 if (doResize || outMatrix.
rows() < ly || outMatrix.
cols() < lx)
1310 outMatrix.
setSize(y_max - y_min + 1, x_max - x_min + 1);
1312 const bool is_color =
isColor();
1315 for (
int y = 0; y < ly; y++)
1317 const uint8_t* pixels = ptr<uint8_t>(x_min, y_min + y);
1318 for (
int x = 0; x < lx; x++)
1322 unsigned int aux = *pixels++ * 3000;
1323 aux += *pixels++ * 5900;
1324 aux += *pixels++ * 1100;
1325 outMatrix.
coeffRef(y, x) =
static_cast<uint8_t
>(aux / 1000);
1329 outMatrix.
coeffRef(y, x) = (*pixels++);
1346 const auto& img =
m_impl->img;
1349 if (x_max == -1) x_max = img.cols - 1;
1350 if (y_max == -1) y_max = img.rows - 1;
1352 ASSERT_(x_min >= 0 && x_min < img.cols && x_min < x_max);
1353 ASSERT_(y_min >= 0 && y_min < img.rows && y_min < y_max);
1355 int lx = (x_max - x_min + 1);
1356 int ly = (y_max - y_min + 1);
1358 if (doResize ||
R.rows() < ly ||
R.cols() < lx)
R.setSize(ly, lx);
1359 if (doResize ||
G.rows() < ly ||
G.cols() < lx)
G.setSize(ly, lx);
1362 const bool is_color =
isColor();
1363 for (
int y = 0; y < ly; y++)
1365 const uint8_t* pixels = ptr<uint8_t>(x_min, y_min + y);
1366 for (
int x = 0; x < lx; x++)
1370 R.coeffRef(y, x) =
u8tof(*pixels++);
1371 G.coeffRef(y, x) =
u8tof(*pixels++);
1376 R.coeffRef(y, x) =
G.coeffRef(y, x) = B.
coeffRef(y, x) =
1395 const auto& img =
m_impl->img;
1398 if (x_max == -1) x_max = img.cols - 1;
1399 if (y_max == -1) y_max = img.rows - 1;
1401 ASSERT_(x_min >= 0 && x_min < img.cols && x_min < x_max);
1402 ASSERT_(y_min >= 0 && y_min < img.rows && y_min < y_max);
1404 int lx = (x_max - x_min + 1);
1405 int ly = (y_max - y_min + 1);
1407 if (doResize ||
R.rows() < ly ||
R.cols() < lx)
R.setSize(ly, lx);
1408 if (doResize ||
G.rows() < ly ||
G.cols() < lx)
G.setSize(ly, lx);
1411 const bool is_color =
isColor();
1412 for (
int y = 0; y < ly; y++)
1414 const uint8_t* pixels = ptr<uint8_t>(x_min, y_min + y);
1415 for (
int x = 0; x < lx; x++)
1419 R.coeffRef(y, x) = *pixels++;
1420 G.coeffRef(y, x) = *pixels++;
1425 R.coeffRef(y, x) =
G.coeffRef(y, x) = B.
coeffRef(y, x) =
1437 int v_search_ini,
int u_search_size,
int v_search_size,
float biasThisImg,
1438 float biasInImg)
const
1445 if (u_search_ini == -1) u_search_ini = 0;
1446 if (v_search_ini == -1) v_search_ini = 0;
1447 if (u_search_size == -1) u_search_size =
static_cast<int>(
getWidth());
1448 if (v_search_size == -1) v_search_size =
static_cast<int>(
getHeight());
1450 int u_search_end = u_search_ini + u_search_size - 1;
1451 int v_search_end = v_search_ini + v_search_size - 1;
1459 std::max(
static_cast<size_t>(u_search_size), in_img.
getWidth());
1461 std::max(
static_cast<size_t>(v_search_size), in_img.
getHeight());
1462 size_t lx = mrpt::round2up<size_t>(actual_lx);
1463 size_t ly = mrpt::round2up<size_t>(actual_ly);
1471 i2.
fill(biasThisImg);
1475 i2,
false, u_search_ini, v_search_ini, u_search_ini + u_search_size - 1,
1476 v_search_ini + v_search_size - 1);
1484 CMatrixF I1_R, I1_I, I2_R, I2_I, ZEROS(ly, lx);
1489 for (y = 0; y < ly; y++)
1490 for (x = 0; x < lx; x++)
1492 float r1 = I1_R(y, x);
1493 float r2 = I2_R(y, x);
1495 float ii1 = I1_I(y, x);
1496 float ii2 = I2_I(y, x);
1499 I2_R(y, x) = (r1 * r2 + ii1 * ii2) / den;
1500 I2_I(y, x) = (ii2 * r1 - r2 * ii1) / den;
1507 out_corr.
setSize(actual_ly, actual_lx);
1508 for (y = 0; y < actual_ly; y++)
1509 for (x = 0; x < actual_lx; x++)
1510 out_corr(y, x) = sqrt(
square(res_R(y, x)) +
square(res_I(y, x)));
1521 const auto& img =
m_impl->img;
1524 const auto matrix_lx = outMatrix.
cols();
1525 const auto matrix_ly = outMatrix.
rows();
1532 unsigned char* min_pixels = (*this)(0, y % img.rows, 0);
1533 unsigned char* max_pixels = min_pixels + img.cols * 3;
1534 unsigned char* pixels = min_pixels;
1538 aux = *pixels++ * 0.30f;
1539 aux += *pixels++ * 0.59f;
1540 aux += *pixels++ * 0.11f;
1541 outMatrix(y, x) = aux;
1542 if (pixels >= max_pixels) pixels = min_pixels;
1550 unsigned char* min_pixels = (*this)(0, y % img.rows, 0);
1551 unsigned char* max_pixels = min_pixels + img.
cols;
1552 unsigned char* pixels = min_pixels;
1555 outMatrix(y, x) = *pixels++;
1556 if (pixels >= max_pixels) pixels = min_pixels;
1574 m_externalFile = fileName;
1575 m_imgIsExternalStorage =
true;
1588 if (!
m_impl->img.empty())
return;
1609 "Error loading externally-stored image from: %s",
1615 "Trying to access uninitialized image in a non "
1616 "externally-stored "
1663 cv::cvtColor(
m_impl->img,
m_impl->img, cv::COLOR_RGB2BGR);
1672 auto& srcImg =
m_impl->img;
1673 cv::Mat outImg(srcImg.rows, srcImg.cols, srcImg.type());
1675 auto mapXm =
static_cast<cv::Mat*
>(mapX);
1676 auto mapYm =
static_cast<cv::Mat*
>(mapX);
1678 cv::remap(srcImg, outImg, *mapXm, *mapYm, cv::INTER_CUBIC);
1693 "In-place undistort() not supported");
1695 auto& srcImg =
const_cast<cv::Mat&
>(
m_impl->img);
1700 const auto& dist = cameraParams.
dist;
1702 cv::Mat distM(1, dist.size(), CV_64F,
const_cast<double*
>(&dist[0]));
1703 cv::Mat inMat(3, 3, CV_64F);
1705 for (
int i = 0; i < 3; i++)
1706 for (
int j = 0; j < 3; j++) inMat.at<
double>(i, j) = intrMat(i, j);
1708 cv::undistort(srcImg, out_img.
m_impl->img, inMat, distM);
1717 auto srcImg =
const_cast<cv::Mat&
>(
m_impl->img);
1718 if (
this == &out_img)
1719 srcImg = srcImg.clone();
1723 cv::medianBlur(srcImg, out_img.
m_impl->img, W);
1731 auto srcImg =
const_cast<cv::Mat&
>(
m_impl->img);
1732 if (
this == &out_img)
1733 srcImg = srcImg.clone();
1737 cv::GaussianBlur(srcImg, out_img.
m_impl->img, cv::Size(W, H), sigma);
1742 CImage& out_img,
unsigned int width,
unsigned int height,
1748 auto srcImg =
m_impl->img;
1750 if (out_img.
m_impl->img.data == srcImg.data) srcImg = srcImg.clone();
1755 out_img.
m_impl->img = srcImg;
1762 srcImg, out_img.
m_impl->img, out_img.
m_impl->img.size(), 0, 0,
1768 CImage& out_img,
double ang,
unsigned int cx,
unsigned int cy,
1774 auto srcImg =
m_impl->img;
1776 if (out_img.
m_impl->img.data == srcImg.data) srcImg = srcImg.clone();
1784 double m[2 * 3] = {scale * cos(ang), -scale * sin(ang), 1.0 * cx,
1785 scale * sin(ang), scale * cos(ang), 1.0 * cy};
1786 cv::Mat M(2, 3, CV_64F, m);
1788 double dx = (srcImg.cols - 1) * 0.5;
1789 double dy = (srcImg.rows - 1) * 0.5;
1790 m[2] -= m[0] * dx + m[1] * dy;
1791 m[5] -= m[3] * dx + m[4] * dy;
1794 srcImg, out_img.
m_impl->img, M, out_img.
m_impl->img.size(),
1795 cv::INTER_LINEAR + cv::WARP_INVERSE_MAP, cv::BORDER_REPLICATE);
1800 std::vector<TPixelCoordf>& cornerCoords,
unsigned int check_size_x,
1801 unsigned int check_size_y,
unsigned int lines_width,
unsigned int r)
1809 unsigned int x, y, i;
1810 cv::Point prev_pt = cvPoint(0, 0);
1811 const int line_max = 8;
1814 line_colors[0] = CV_RGB(255, 0, 0);
1815 line_colors[1] = CV_RGB(255, 128, 0);
1816 line_colors[2] = CV_RGB(255, 128, 0);
1817 line_colors[3] = CV_RGB(200, 200, 0);
1818 line_colors[4] = CV_RGB(0, 255, 0);
1819 line_colors[5] = CV_RGB(0, 200, 200);
1820 line_colors[6] = CV_RGB(0, 0, 255);
1821 line_colors[7] = CV_RGB(255, 0, 255);
1827 const auto color = line_colors[y % line_max];
1831 pt.x = cvRound(cornerCoords[i].x);
1832 pt.y = cvRound(cornerCoords[i].y);
1834 if (i != 0) cv::line(img, prev_pt, pt, color, lines_width);
1837 img, cvPoint(pt.x - r, pt.y - r), cvPoint(pt.x + r, pt.y + r),
1838 color, lines_width);
1840 img, cvPoint(pt.x - r, pt.y + r), cvPoint(pt.x + r, pt.y - r),
1841 color, lines_width);
1843 if (r > 0) cv::circle(img, pt, r + 1, color);
1848 if (i == 0 || i == cornerCoords.size() - 1)
1873 if (&ret !=
this) ret = *
this;
1877 auto srcImg =
m_impl->img;
1879 if (srcImg.data == ret.
m_impl->img.data) srcImg = srcImg.clone();
1883 cv::cvtColor(srcImg, ret.
m_impl->img, cv::COLOR_GRAY2BGR);
1893 ASSERT_(im1.type() == im2.type());
1897 im1.copyTo(img(cv::Rect(0, 0, im1.cols, im1.rows)));
1898 im2.copyTo(img(cv::Rect(im1.cols, 0, im2.cols, im2.rows)));
1906 auto srcImg =
m_impl->img;
1907 if (
this != &out_img)
1909 auto outImg = out_img.
m_impl->img;
1911 if (srcImg.channels() == 1)
1912 cv::equalizeHist(srcImg, outImg);
1920 #if defined(__GNUC__)
1921 #define MRPT_DISABLE_FULL_OPTIMIZATION __attribute__((optimize("O1")))
1923 #define MRPT_DISABLE_FULL_OPTIMIZATION
1926 template <
unsigned int HALF_WIN_SIZE>
1928 const uint8_t* in,
const int widthStep,
unsigned int x,
unsigned int y,
1929 int32_t& _gxx, int32_t& _gyy, int32_t& _gxy)
1931 const auto min_x = x - HALF_WIN_SIZE;
1932 const auto min_y = y - HALF_WIN_SIZE;
1938 const unsigned int WIN_SIZE = 1 + 2 * HALF_WIN_SIZE;
1940 unsigned int yy = min_y;
1941 for (
unsigned int iy = WIN_SIZE; iy; --iy, ++yy)
1943 const uint8_t* ptr = in + widthStep * yy + min_x;
1944 unsigned int xx = min_x;
1945 for (
unsigned int ix = WIN_SIZE; ix; --ix, ++xx, ++ptr)
1948 static_cast<int32_t
>(ptr[+1]) -
static_cast<int32_t
>(ptr[-1]);
1949 const int32_t dy =
static_cast<int32_t
>(ptr[+widthStep]) -
1950 static_cast<int32_t
>(ptr[-widthStep]);
1962 const unsigned int x,
const unsigned int y,
1963 const unsigned int half_window_size)
const
1967 const auto& im1 =
m_impl->img;
1968 const auto img_w =
static_cast<unsigned int>(im1.cols),
1969 img_h =
static_cast<unsigned int>(im1.rows);
1970 const int widthStep = im1.step[0];
1973 const unsigned int min_x = x - half_window_size;
1974 const unsigned int max_x = x + half_window_size;
1975 const unsigned int min_y = y - half_window_size;
1976 const unsigned int max_y = y + half_window_size;
1981 min_x < img_w && max_x < img_w && min_y < img_h && max_y < img_h,
1982 "Window is out of image bounds");
1990 const auto* img_data = im1.ptr<uint8_t>(0);
1991 switch (half_window_size)
1994 image_KLT_response_template<2>(
1995 img_data, widthStep, x, y, gxx, gyy, gxy);
1998 image_KLT_response_template<3>(
1999 img_data, widthStep, x, y, gxx, gyy, gxy);
2002 image_KLT_response_template<4>(
2003 img_data, widthStep, x, y, gxx, gyy, gxy);
2006 image_KLT_response_template<5>(
2007 img_data, widthStep, x, y, gxx, gyy, gxy);
2010 image_KLT_response_template<6>(
2011 img_data, widthStep, x, y, gxx, gyy, gxy);
2014 image_KLT_response_template<7>(
2015 img_data, widthStep, x, y, gxx, gyy, gxy);
2018 image_KLT_response_template<8>(
2019 img_data, widthStep, x, y, gxx, gyy, gxy);
2022 image_KLT_response_template<9>(
2023 img_data, widthStep, x, y, gxx, gyy, gxy);
2026 image_KLT_response_template<10>(
2027 img_data, widthStep, x, y, gxx, gyy, gxy);
2030 image_KLT_response_template<11>(
2031 img_data, widthStep, x, y, gxx, gyy, gxy);
2034 image_KLT_response_template<12>(
2035 img_data, widthStep, x, y, gxx, gyy, gxy);
2038 image_KLT_response_template<13>(
2039 img_data, widthStep, x, y, gxx, gyy, gxy);
2042 image_KLT_response_template<14>(
2043 img_data, widthStep, x, y, gxx, gyy, gxy);
2046 image_KLT_response_template<15>(
2047 img_data, widthStep, x, y, gxx, gyy, gxy);
2050 image_KLT_response_template<16>(
2051 img_data, widthStep, x, y, gxx, gyy, gxy);
2054 image_KLT_response_template<32>(
2055 img_data, widthStep, x, y, gxx, gyy, gxy);
2059 for (
unsigned int yy = min_y; yy <= max_y; yy++)
2061 const uint8_t* p = img_data + widthStep * yy + min_x;
2062 for (
unsigned int xx = min_x; xx <= max_x; xx++)
2064 const int32_t dx = p[+1] - p[-1];
2065 const int32_t dy = p[+widthStep] - p[-widthStep];
2074 const float K = 0.5f / ((max_y - min_y + 1) * (max_x - min_x + 1));
2075 const float Gxx = gxx * K;
2076 const float Gxy = gxy * K;
2077 const float Gyy = gyy * K;
2084 const float t = Gxx + Gyy;
2085 const float de = Gxx * Gyy - Gxy * Gxy;
2087 return 0.5f * (t - std::sqrt(t * t - 4.0f * de));
2102 std::fstream stream;
2103 stream.open(fileName.c_str(), std::fstream::in | std::fstream::binary);
2104 if (!stream.is_open())
2106 std::cerr <<
"[CImage::loadTGA] Couldn't open file '" << fileName
2113 stream.seekg(0, std::ios_base::beg);
2116 char dumpBuffer[12];
2117 char trueColorHeader[] =
"\0\0\2\0\0\0\0\0\0\0\0\0";
2118 stream.read(dumpBuffer, 12);
2119 if (memcmp(dumpBuffer, trueColorHeader, 12) != 0)
2121 std::cerr <<
"[CImage::loadTGA] Unsupported format or invalid file.\n";
2125 unsigned short width, height;
2128 stream.read((
char*)&width, 2);
2129 stream.read((
char*)&height, 2);
2133 std::cerr <<
"[CImage::loadTGA] Only 32 bpp format supported!\n";
2138 desc = stream.get();
2139 if (desc != 8 && desc != 32)
2141 std::cerr <<
"[CImage::loadTGA] Unsupported format or invalid file.\n";
2144 const bool origin_is_low_corner = (desc == 8);
2147 std::vector<uint8_t> bytes(width * height * 4);
2148 stream.read((
char*)&bytes[0], width * height * 4);
2156 for (
int r = 0; r < height; r++)
2158 const auto actual_row = origin_is_low_corner ? (height - 1 - r) : r;
2159 auto& img = out_RGB.
m_impl->img;
2160 auto data = img.ptr<uint8_t>(actual_row);
2162 auto& img_alpha = out_alpha.
m_impl->img;
2163 auto data_alpha = img_alpha.ptr<uint8_t>(actual_row);
2165 for (
unsigned int c = 0; c < width; c++)
2167 *
data++ = bytes[idx++];
2168 *
data++ = bytes[idx++];
2169 *
data++ = bytes[idx++];
2170 *data_alpha++ = bytes[idx++];
2177 #endif // MRPT_HAS_OPENCV
2186 *dest = cvIplImage(
m_impl->img);
2192 o <<
"(" << p.
x <<
"," << p.
y <<
")";
2197 o <<
"(" << p.
x <<
"," << p.
y <<
")";