29 #include <mrpt/otherlibs/do_opencv_includes.h> 34 #include <mexplus/mxarray.h> 78 :
std::runtime_error(
s)
89 #define IMAGE_ALLOC_PERFLOG 0 91 #if IMAGE_ALLOC_PERFLOG 110 template <
typename RET = u
int32_t>
125 return std::numeric_limits<RET>::max();
127 template <
typename RET = u
int32_t>
142 return std::numeric_limits<RET>::max();
162 #endif // MRPT_HAS_OPENCV 219 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
227 out_img =
m_impl->img.clone();
239 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
249 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
266 _IplImage ipl =
m_impl->img;
268 if (static_cast<unsigned>(ipl.width) ==
width &&
269 static_cast<unsigned>(ipl.height) ==
height &&
270 ipl.nChannels == nChannels &&
278 #if IMAGE_ALLOC_PERFLOG 280 alloc_tims.enter(sLog.c_str());
288 pixelDepth2CvDepth<int>(
depth) + ((nChannels - 1) << CV_CN_SHIFT));
290 #if IMAGE_ALLOC_PERFLOG 291 alloc_tims.leave(sLog.c_str());
295 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
306 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
317 #ifdef HAVE_OPENCV_IMGCODECS 319 MRPT_TODO(
"add flag to reuse current img buffer");
321 m_impl->img = cv::imread(fileName, static_cast<cv::ImreadModes>(
isColor));
324 if (!newImg)
return false;
325 m_impl->img = cv::cvarrToMat(newImg);
327 if (
m_impl->img.empty())
return false;
331 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
343 #ifdef HAVE_OPENCV_IMGCODECS 344 const std::vector<int>
params = {cv::IMWRITE_JPEG_QUALITY, jpeg_quality};
347 int p[3] = {CV_IMWRITE_JPEG_QUALITY, jpeg_quality, 0};
348 _IplImage ipl =
m_impl->img;
349 return (0 != cvSaveImage(fileName.c_str(), &ipl,
p));
352 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
364 cv::cvarrToMat(iplImage,
c ==
DEEP_COPY ?
true :
false );
366 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
373 unsigned char* rawpixels,
bool swapRedBlue)
381 _IplImage ii(
m_impl->img);
384 if (
color && swapRedBlue)
387 unsigned char* ptr_src = rawpixels;
388 auto* ptr_dest =
reinterpret_cast<unsigned char*
>(
img->imageData);
389 const int bytes_per_row_out =
img->widthStep;
391 for (
int h =
height; h--;)
393 for (
unsigned int i = 0; i <
width;
394 i++, ptr_src += 3, ptr_dest += 3)
396 unsigned char t0 = ptr_src[0], t1 = ptr_src[1], t2 = ptr_src[2];
401 ptr_dest += bytes_per_row_out -
width * 3;
406 if (
img->widthStep ==
img->width *
img->nChannels)
414 unsigned char* ptr_src = rawpixels;
415 auto* ptr_dest =
reinterpret_cast<unsigned char*
>(
img->imageData);
417 int bytes_per_row_out =
img->widthStep;
418 for (
unsigned int y = 0;
y <
height;
y++)
420 memcpy(ptr_dest, ptr_src, bytes_per_row);
421 ptr_src += bytes_per_row;
422 ptr_dest += bytes_per_row_out;
427 THROW_EXCEPTION(
"The MRPT has been compiled with MRPT_HAS_OPENCV=0 !");
433 unsigned int ucol,
unsigned int urow,
unsigned int uchannel)
const 437 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG) 442 const auto col =
static_cast<int>(ucol);
443 const auto row =
static_cast<int>(urow);
444 const auto channel =
static_cast<int>(uchannel);
446 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG) 449 channel >=
m_impl->img.channels())
452 "Pixel coordinates/channel out of bounds: row=%u/%u col=%u/%u " 460 return const_cast<unsigned char*
>(
p);
461 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG) 483 unsigned int col,
unsigned int row,
uint8_t channel)
const 515 const bool hasColor =
m_impl->img.empty() ? false :
isColor();
539 out << imageStoredAsZip;
542 if (imageStoredAsZip)
544 std::vector<unsigned char> tempBuf;
548 auto zipDataLen =
static_cast<int32_t>(tempBuf.size());
594 out << neg_width << neg_height;
597 const auto bytes_per_row =
width * 3;
618 "[CImage] Cannot deserialize image since MRPT has been " 619 "compiled without OpenCV");
639 in >>
width >>
height >> nChannels >> originTopLeft >> imgLength;
642 in.ReadBuffer(
m_impl->img.data, imgLength);
696 static_cast<uint32_t>(
width),
700 static_cast<uint32_t>(
width) *
701 static_cast<uint32_t>(
height) *
712 bool imageIsZIP =
true;
716 if (version == 4 &&
imageSize <= 16 * 1024)
732 size_t outDataActualSize;
735 outDataBufferSize, outDataActualSize);
736 ASSERT_(outDataActualSize == outDataBufferSize);
739 "ZIP image deserialization not " 753 bool loadJPEG =
true;
777 const size_t bytes_per_row =
img.cols * 3;
778 for (
int y = 0;
y <
img.rows;
y++)
780 const size_t nRead =
in.ReadBuffer(
781 img.ptr<
void>(
y), bytes_per_row);
782 if (nRead != bytes_per_row)
784 "Error: Truncated data stream " 785 "while parsing raw image?");
829 cv::Mat cvImg = cv::cvarrToMat(this->getAs<IplImage>());
830 return mexplus::from(cvImg);
872 return m_impl->img.step[0];
892 return m_impl->img.channels() == 3;
914 unsigned int col,
unsigned int row,
unsigned int channel)
const 918 return (*(*
this)(col,
row, channel)) / 255.0f;
927 unsigned char*
pixels = (*this)(col,
row, 0);
934 return (*(*
this)(col,
row, 0 )) / 255.0f;
947 for (
x = 0;
x < cx;
x++)
964 if (dest.size() !=
src.size() || dest.type() !=
src.type())
965 dest = cv::Mat(
src.rows,
src.cols, CV_8UC1);
969 if ((
src.step[0] & 0x0f) == 0 && (dest.step[0] & 0x0f) == 0)
973 src.step[0], dest.step[0]);
978 cv::cvtColor(
src, dest, CV_BGR2GRAY);
988 if (
m_impl->img.channels() == 1)
1003 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
1013 const int w =
img.cols, h =
img.rows;
1017 auto& img_out = out.
m_impl->img;
1024 img.data, img_out.data,
w, h,
img.step[0], img_out.step[0]);
1029 if (
img.channels() == 1)
1034 img.data, img_out.data,
w, h,
img.step[0], img_out.step[0]);
1040 img.data, img_out.data,
w, h,
img.step[0], img_out.step[0]);
1051 THROW_EXCEPTION(
"Operation not supported: build MRPT against OpenCV!");
1063 unsigned int width,
unsigned int height,
unsigned int bytesPerRow,
1064 unsigned char*
red,
unsigned char*
green,
unsigned char*
blue)
1072 for (
unsigned int y = 0;
y <
height;
y++)
1078 unsigned char* srcR =
red + bytesPerRow *
y;
1079 unsigned char* srcG =
green + bytesPerRow *
y;
1080 unsigned char* srcB =
blue + bytesPerRow *
y;
1082 for (
unsigned int x = 0;
x <
width;
x++)
1084 *(dest++) = *(srcB++);
1085 *(dest++) = *(srcG++);
1086 *(dest++) = *(srcR++);
1098 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG) 1107 if (x >= 0 &&
y >= 0 &&
y <
img.rows &&
x <
img.cols)
1110 if (
img.channels() == 1)
1116 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG) 1128 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG) 1143 m_impl->img, cv::Point(x0, y0), cv::Point(x1, y1),
1156 static_cast<int>(
width));
1164 img.makeSureImageIsLoaded();
1166 cv::Rect roi(cv::Point(
x,
y), cv::Size(
img.getWidth(),
img.getHeight()));
1167 cv::Mat dest =
m_impl->img(roi);
1168 img.m_impl->img.copyTo(dest);
1173 const CImage& patch,
const unsigned int col_,
const unsigned int row_)
1178 auto& dest = patch.
m_impl->img;
1180 src(cv::Rect(col_, row_, dest.cols, dest.rows)).copyTo(dest);
1185 CImage& patch,
const unsigned int col_,
const unsigned int row_,
1186 const unsigned int col_num,
const unsigned int row_num)
const 1191 auto& dest = patch.
m_impl->img;
1193 src(cv::Rect(col_, row_, col_num, row_num)).copyTo(dest);
1198 const CImage& img2,
int width_init,
int height_init)
const 1205 THROW_EXCEPTION(
"Correlation Error!, image to correlate out of bounds");
1209 float syy = 0.0f, sxy = 0.0f, sxx = 0.0f, m1 = 0.0f, m2 = 0.0f,
1217 for (j = 0; j < img2.
getWidth(); j++)
1232 for (j = 0; j < img2.
getWidth(); j++)
1234 x1 = *(*this)(j + width_init, i + height_init) -
1237 x2 = *img2(j, i) - m2;
1245 return sxy / sqrt(sxx * syy);
1260 CMatrixFloat& outMatrix,
bool doResize,
int x_min,
int y_min,
int x_max,
1261 int y_max,
bool normalize_01)
const 1270 if (x_max == -1) x_max =
img.cols - 1;
1271 if (y_max == -1) y_max =
img.rows - 1;
1273 ASSERT_(x_min >= 0 && x_min <
img.cols && x_min < x_max);
1274 ASSERT_(y_min >= 0 && y_min <
img.rows && y_min < y_max);
1276 int lx = (x_max - x_min + 1);
1277 int ly = (y_max - y_min + 1);
1279 if (doResize || outMatrix.
rows() < ly || outMatrix.
cols() < lx)
1280 outMatrix.
setSize(y_max - y_min + 1, x_max - x_min + 1);
1285 for (
int y = 0;
y < ly;
y++)
1288 for (
int x = 0;
x < lx;
x++)
1290 float aux = *
pixels++ * 0.3f;
1291 aux += *
pixels++ * 0.59f;
1292 aux += *
pixels++ * 0.11f;
1293 if (normalize_01) aux *= (1.0f / 255);
1300 for (
int y = 0;
y < ly;
y++)
1303 for (
int x = 0;
x < lx;
x++)
1306 if (normalize_01) aux *= (1.0f / 255);
1328 if (x_max == -1) x_max =
img.cols - 1;
1329 if (y_max == -1) y_max =
img.rows - 1;
1331 ASSERT_(x_min >= 0 && x_min <
img.cols && x_min < x_max);
1332 ASSERT_(y_min >= 0 && y_min <
img.rows && y_min < y_max);
1334 int lx = (x_max - x_min + 1);
1335 int ly = (y_max - y_min + 1);
1337 if (doResize ||
R.rows() < ly ||
R.cols() < lx)
R.setSize(ly, lx);
1338 if (doResize ||
G.rows() < ly ||
G.cols() < lx)
G.setSize(ly, lx);
1343 for (
int y = 0;
y < ly;
y++)
1346 for (
int x = 0;
x < lx;
x++)
1348 float aux = *
pixels++ * (1.0f / 255);
1349 R.coeffRef(
y,
x) = aux;
1350 aux = *
pixels++ * (1.0f / 255);
1351 G.coeffRef(
y,
x) = aux;
1352 aux = *
pixels++ * (1.0f / 255);
1359 for (
int y = 0;
y < ly;
y++)
1362 for (
int x = 0;
x < lx;
x++)
1364 R.coeffRef(
y,
x) = (*pixels) * (1.0f / 255);
1365 G.coeffRef(
y,
x) = (*pixels) * (1.0f / 255);
1377 int v_search_ini,
int u_search_size,
int v_search_size,
float biasThisImg,
1378 float biasInImg)
const 1385 if (u_search_ini == -1) u_search_ini = 0;
1386 if (v_search_ini == -1) v_search_ini = 0;
1387 if (u_search_size == -1) u_search_size =
static_cast<int>(
getWidth());
1388 if (v_search_size == -1) v_search_size =
static_cast<int>(
getHeight());
1390 int u_search_end = u_search_ini + u_search_size - 1;
1391 int v_search_end = v_search_ini + v_search_size - 1;
1399 std::max(static_cast<size_t>(u_search_size), in_img.
getWidth());
1401 std::max(static_cast<size_t>(v_search_size), in_img.
getHeight());
1402 size_t lx = mrpt::round2up<size_t>(actual_lx);
1403 size_t ly = mrpt::round2up<size_t>(actual_ly);
1411 i2.fill(biasThisImg);
1415 i2,
false, u_search_ini, v_search_ini, u_search_ini + u_search_size - 1,
1416 v_search_ini + v_search_size - 1);
1424 CMatrixF I1_R, I1_I, I2_R, I2_I, ZEROS(ly, lx);
1429 for (
y = 0;
y < ly;
y++)
1430 for (
x = 0;
x < lx;
x++)
1432 float r1 = I1_R(
y,
x);
1433 float r2 = I2_R(
y,
x);
1435 float ii1 = I1_I(
y,
x);
1436 float ii2 = I2_I(
y,
x);
1439 I2_R(
y,
x) = (r1 * r2 + ii1 * ii2) / den;
1440 I2_I(
y,
x) = (ii2 * r1 - r2 * ii1) / den;
1447 out_corr.
setSize(actual_ly, actual_lx);
1448 for (
y = 0;
y < actual_ly;
y++)
1449 for (
x = 0;
x < actual_lx;
x++)
1464 const auto matrix_lx = outMatrix.
cols();
1465 const auto matrix_ly = outMatrix.
rows();
1472 unsigned char* min_pixels = (*this)(0,
y %
img.rows, 0);
1473 unsigned char* max_pixels = min_pixels +
img.cols * 3;
1474 unsigned char*
pixels = min_pixels;
1479 aux += *
pixels++ * 0.59f;
1480 aux += *
pixels++ * 0.11f;
1481 outMatrix(
y,
x) = aux;
1490 unsigned char* min_pixels = (*this)(0,
y %
img.rows, 0);
1491 unsigned char* max_pixels = min_pixels +
img.
cols;
1492 unsigned char*
pixels = min_pixels;
1514 m_externalFile = fileName;
1515 m_imgIsExternalStorage =
true;
1528 if (!
m_impl->img.empty())
return;
1549 "Error loading externally-stored image from: %s",
1555 "Trying to access uninitialized image in a non " 1556 "externally-stored " 1603 cv::cvtColor(
m_impl->img,
m_impl->img, cv::COLOR_RGB2BGR);
1612 auto& srcImg =
m_impl->img;
1613 cv::Mat outImg(srcImg.rows, srcImg.cols, srcImg.type());
1615 auto mapXm =
static_cast<cv::Mat*
>(mapX);
1616 auto mapYm =
static_cast<cv::Mat*
>(mapX);
1618 cv::remap(srcImg, outImg, *mapXm, *mapYm, cv::INTER_CUBIC);
1633 "In-place undistort() not supported");
1635 auto& srcImg =
const_cast<cv::Mat&
>(
m_impl->img);
1640 const auto& dist = cameraParams.
dist;
1642 cv::Mat distM(1, 5, CV_64F, const_cast<double*>(&dist[0]));
1643 cv::Mat inMat(3, 3, CV_64F);
1645 for (
int i = 0; i < 3; i++)
1646 for (
int j = 0; j < 3; j++) inMat.at<
double>(i, j) = intrMat(i, j);
1648 cv::undistort(srcImg, out_img.
m_impl->img, inMat, distM);
1658 auto srcImg =
const_cast<cv::Mat&
>(
m_impl->img);
1659 if (
this == &out_img)
1660 srcImg = srcImg.clone();
1664 cv::medianBlur(srcImg, out_img.
m_impl->img, W);
1672 auto srcImg =
const_cast<cv::Mat&
>(
m_impl->img);
1673 if (
this == &out_img)
1674 srcImg = srcImg.clone();
1678 cv::GaussianBlur(srcImg, out_img.
m_impl->img, cv::Size(W, H), sigma);
1689 auto srcImg =
m_impl->img;
1691 if (out_img.
m_impl->img.data == srcImg.data) srcImg = srcImg.clone();
1696 out_img.
m_impl->img = srcImg;
1703 srcImg, out_img.
m_impl->img, out_img.
m_impl->img.size(), 0, 0,
1709 CImage& out_img,
double ang,
unsigned int cx,
unsigned int cy,
1715 auto srcImg =
m_impl->img;
1717 if (out_img.
m_impl->img.data == srcImg.data) srcImg = srcImg.clone();
1725 double m[2 * 3] = {
scale * cos(ang), -
scale * sin(ang), 1.0 * cx,
1726 scale * sin(ang),
scale * cos(ang), 1.0 * cy};
1727 cv::Mat M(2, 3, CV_64F, m);
1729 double dx = (srcImg.cols - 1) * 0.5;
1730 double dy = (srcImg.rows - 1) * 0.5;
1731 m[2] -= m[0] * dx + m[1] * dy;
1732 m[5] -= m[3] * dx + m[4] * dy;
1735 srcImg, out_img.
m_impl->img, M, out_img.
m_impl->img.size(),
1736 cv::INTER_LINEAR + cv::WARP_INVERSE_MAP, cv::BORDER_REPLICATE);
1741 std::vector<TPixelCoordf>& cornerCoords,
unsigned int check_size_x,
1742 unsigned int check_size_y,
unsigned int lines_width,
unsigned int r)
1746 if (cornerCoords.size() != check_size_x * check_size_y)
return false;
1750 unsigned int x,
y, i;
1751 CvPoint prev_pt = cvPoint(0, 0);
1752 const int line_max = 8;
1753 CvScalar line_colors[8];
1755 line_colors[0] = CV_RGB(255, 0, 0);
1756 line_colors[1] = CV_RGB(255, 128, 0);
1757 line_colors[2] = CV_RGB(255, 128, 0);
1758 line_colors[3] = CV_RGB(200, 200, 0);
1759 line_colors[4] = CV_RGB(0, 255, 0);
1760 line_colors[5] = CV_RGB(0, 200, 200);
1761 line_colors[6] = CV_RGB(0, 0, 255);
1762 line_colors[7] = CV_RGB(255, 0, 255);
1769 for (
y = 0, i = 0;
y < check_size_y;
y++)
1771 CvScalar
color = line_colors[
y % line_max];
1772 for (
x = 0;
x < check_size_x;
x++, i++)
1775 pt.x = cvRound(cornerCoords[i].
x);
1776 pt.y = cvRound(cornerCoords[i].
y);
1778 if (i != 0) cvLine(ipl, prev_pt, pt,
color, lines_width);
1781 ipl, cvPoint(pt.x -
r, pt.y -
r), cvPoint(pt.x +
r, pt.y +
r),
1782 color, lines_width);
1784 ipl, cvPoint(pt.x -
r, pt.y +
r), cvPoint(pt.x +
r, pt.y -
r),
1785 color, lines_width);
1787 if (
r > 0) cvCircle(ipl, pt,
r + 1,
color);
1792 if (i == 0 || i == cornerCoords.size() - 1)
1817 if (&ret !=
this) ret = *
this;
1821 auto srcImg =
m_impl->img;
1823 if (srcImg.data == ret.
m_impl->img.data) srcImg = srcImg.clone();
1827 cv::cvtColor(srcImg, ret.
m_impl->img, cv::COLOR_GRAY2BGR);
1837 ASSERT_(im1.type() == im2.type());
1841 im1.copyTo(
img(cv::Rect(0, 0, im1.cols, im1.rows)));
1842 im2.copyTo(
img(cv::Rect(im1.cols, 0, im2.cols, im2.rows)));
1850 auto srcImg =
m_impl->img;
1851 if (
this != &out_img)
1853 auto outImg = out_img.
m_impl->img;
1855 if (srcImg.channels() == 1)
1856 cv::equalizeHist(srcImg, outImg);
1864 #if defined(__GNUC__) 1865 #define MRPT_DISABLE_FULL_OPTIMIZATION __attribute__((optimize("O1"))) 1867 #define MRPT_DISABLE_FULL_OPTIMIZATION 1870 template <
unsigned int HALF_WIN_SIZE>
1872 const uint8_t*
in,
const int widthStep,
unsigned int x,
unsigned int y,
1875 const auto min_x =
x - HALF_WIN_SIZE;
1876 const auto min_y =
y - HALF_WIN_SIZE;
1882 const unsigned int WIN_SIZE = 1 + 2 * HALF_WIN_SIZE;
1884 unsigned int yy = min_y;
1885 for (
unsigned int iy = WIN_SIZE; iy; --iy, ++yy)
1887 const uint8_t* ptr =
in + widthStep * yy + min_x;
1888 unsigned int xx = min_x;
1889 for (
unsigned int ix = WIN_SIZE; ix; --ix, ++xx, ++ptr)
1892 static_cast<int32_t>(ptr[+1]) - static_cast<int32_t>(ptr[-1]);
1894 static_cast<int32_t>(ptr[-widthStep]);
1906 const unsigned int x,
const unsigned int y,
1907 const unsigned int half_window_size)
const 1911 const auto& im1 =
m_impl->img;
1912 const auto img_w =
static_cast<unsigned int>(im1.cols),
1913 img_h = static_cast<unsigned int>(im1.rows);
1914 const int widthStep = im1.step[0];
1917 const unsigned int min_x =
x - half_window_size;
1918 const unsigned int max_x =
x + half_window_size;
1919 const unsigned int min_y =
y - half_window_size;
1920 const unsigned int max_y =
y + half_window_size;
1925 min_x < img_w && max_x < img_w && min_y < img_h && max_y < img_h,
1926 "Window is out of image bounds");
1934 const auto* img_data = im1.ptr<
uint8_t>(0);
1935 switch (half_window_size)
1938 image_KLT_response_template<2>(
1939 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1942 image_KLT_response_template<3>(
1943 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1946 image_KLT_response_template<4>(
1947 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1950 image_KLT_response_template<5>(
1951 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1954 image_KLT_response_template<6>(
1955 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1958 image_KLT_response_template<7>(
1959 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1962 image_KLT_response_template<8>(
1963 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1966 image_KLT_response_template<9>(
1967 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1970 image_KLT_response_template<10>(
1971 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1974 image_KLT_response_template<11>(
1975 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1978 image_KLT_response_template<12>(
1979 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1982 image_KLT_response_template<13>(
1983 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1986 image_KLT_response_template<14>(
1987 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1990 image_KLT_response_template<15>(
1991 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1994 image_KLT_response_template<16>(
1995 img_data, widthStep,
x,
y, gxx, gyy, gxy);
1998 image_KLT_response_template<32>(
1999 img_data, widthStep,
x,
y, gxx, gyy, gxy);
2003 for (
unsigned int yy = min_y; yy <= max_y; yy++)
2005 const uint8_t*
p = img_data + widthStep * yy + min_x;
2006 for (
unsigned int xx = min_x; xx <= max_x; xx++)
2009 const int32_t dy =
p[+widthStep] -
p[-widthStep];
2018 const float K = 0.5f / ((max_y - min_y + 1) * (max_x - min_x + 1));
2019 const float Gxx = gxx * K;
2020 const float Gxy = gxy * K;
2021 const float Gyy = gyy * K;
2028 const float t = Gxx + Gyy;
2029 const float de = Gxx * Gyy - Gxy * Gxy;
2031 return 0.5f * (
t - std::sqrt(
t *
t - 4.0f * de));
2046 std::fstream stream;
2048 if (!stream.is_open())
2050 std::cerr <<
"[CImage::loadTGA] Couldn't open file '" << fileName
2057 stream.seekg(0, std::ios_base::beg);
2060 char dumpBuffer[12];
2061 char trueColorHeader[] =
"\0\0\2\0\0\0\0\0\0\0\0\0";
2062 stream.read(dumpBuffer, 12);
2063 if (memcmp(dumpBuffer, trueColorHeader, 12) != 0)
2065 std::cerr <<
"[CImage::loadTGA] Unsupported format or invalid file.\n";
2072 stream.read((
char*)&
width, 2);
2073 stream.read((
char*)&
height, 2);
2077 std::cerr <<
"[CImage::loadTGA] Only 32 bpp format supported!\n";
2082 desc = stream.get();
2083 if (desc != 8 && desc != 32)
2085 std::cerr <<
"[CImage::loadTGA] Unsupported format or invalid file.\n";
2088 const bool origin_is_low_corner = (desc == 8);
2092 stream.read((
char*)&bytes[0],
width *
height * 4);
2102 const auto actual_row = origin_is_low_corner ? (
height - 1 -
r) :
r;
2106 auto& img_alpha = out_alpha.
m_impl->img;
2107 auto data_alpha = img_alpha.ptr<
uint8_t>(actual_row);
2109 for (
unsigned int c = 0;
c <
width;
c++)
2111 *
data++ = bytes[idx++];
2112 *
data++ = bytes[idx++];
2113 *
data++ = bytes[idx++];
2114 *data_alpha++ = bytes[idx++];
2121 #endif // MRPT_HAS_OPENCV 2126 o <<
"(" <<
p.x <<
"," <<
p.y <<
")";
2131 o <<
"(" <<
p.x <<
"," <<
p.y <<
")";
void update_patch(const CImage &patch, const unsigned int col, const unsigned int row)
Update a part of this image with the "patch" given as argument.
void drawCircle(int x, int y, int radius, const mrpt::img::TColor &color=mrpt::img::TColor(255, 255, 255), unsigned int width=1) override
Draws a circle of a given radius.
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei imageSize
void line(int x0, int y0, int x1, int y1, const mrpt::img::TColor color, unsigned int width=1, TPenStyle penStyle=psSolid) override
Draws a line.
Used in mrpt::img::CImage.
void decompress(void *inData, size_t inDataSize, std::vector< unsigned char > &outData, size_t outDataEstimatedSize)
Decompress an array of bytes into another one.
TPenStyle
Definition of pen styles.
bool drawChessboardCorners(std::vector< TPixelCoordf > &cornerCoords, unsigned int check_size_x, unsigned int check_size_y, unsigned int lines_width=1, unsigned int circles_radius=4)
Draw onto this image the detected corners of a chessboard.
void getAsMatrixTiled(mrpt::math::CMatrixFloat &outMatrix) const
Returns the image as a matrix, where the image is "tiled" (repeated) the required number of times to ...
void MRPT_DISABLE_FULL_OPTIMIZATION image_KLT_response_template(const uint8_t *in, const int widthStep, unsigned int x, unsigned int y, int32_t &_gxx, int32_t &_gyy, int32_t &_gxy)
static bool DISABLE_ZIP_COMPRESSION()
#define THROW_EXCEPTION(msg)
CImage scaleHalf(TInterpolationMethod interp) const
Returns a new image scaled down to half its original size.
void getAsMatrix(mrpt::math::CMatrixFloat &outMatrix, bool doResize=true, int x_min=0, int y_min=0, int x_max=-1, int y_max=-1, bool normalize_01=true) const
Returns the image as a matrix with pixel grayscale values in the range [0,1].
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
void image_SSE2_scale_half_smooth_1c8u(const uint8_t *in, uint8_t *out, int w, int h, size_t step_in, size_t step_out)
Average each 2x2 pixels into 1x1 pixel (arithmetic average)
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
To be added to all CSerializable-classes implementation files.
GLenum GLenum GLenum GLenum GLenum scale
void copyFromForceLoad(const CImage &o)
Copies from another image (shallow copy), and, if it is externally stored, the image file will be act...
void getAsRGBMatrices(mrpt::math::CMatrixFloat &outMatrixR, mrpt::math::CMatrixFloat &outMatrixG, mrpt::math::CMatrixFloat &outMatrixB, bool doResize=true, int x_min=0, int y_min=0, int x_max=-1, int y_max=-1) const
Returns the image as RGB matrices with pixel values in the range [0,1].
static bool DISABLE_JPEG_COMPRESSION()
GLdouble GLdouble GLdouble GLdouble q
void image_SSE2_scale_half_1c8u(const uint8_t *in, uint8_t *out, int w, int h, size_t step_in, size_t step_out)
Subsample each 2x2 pixel block into 1x1 pixel, taking the first pixel & ignoring the other 3...
copy_type_t
Define kind of copies.
CExceptionExternalImageNotFound(const std::string &s)
float getMaxAsFloat() const
Return the maximum pixel value of the image, as a float value in the range [0,1]. ...
void drawImage(int x, int y, const mrpt::img::CImage &img) override
Draws an image as a bitmap at a given position.
cv::Mat & asCvMatRef()
Get a reference to the internal cv::Mat, which can be resized, etc.
void flipHorizontal()
Flips the image horizontally.
TImageChannels getChannelCount() const
Returns the number of channels, typically 1 (GRAY) or 3 (RGB)
static constexpr TColor blue()
size_t getHeight() const override
Returns the height of the image in pixels.
void scaleImage(CImage &out_img, unsigned int width, unsigned int height, TInterpolationMethod interp=IMG_INTERP_CUBIC) const
Scales this image to a new size, interpolating as needed, saving the new image in a different output ...
std::string getChannelsOrder() const
As of mrpt 2.0.0, this returns either "GRAY" or "BGR".
A pair (x,y) of pixel coordinates (subpixel resolution).
void setExternalStorage(const std::string &fileName) noexcept
By using this method the image is marked as referenced to an external file, which will be loaded only...
GLint GLint GLsizei GLsizei GLsizei depth
float correlate(const CImage &img2int, int width_init=0, int height_init=0) const
Computes the correlation coefficient (returned as val), between two images This function use grayscal...
void makeSureImageIsLoaded() const
Checks if the image is of type "external storage", and if so and not loaded yet, load it...
void filterGaussian(CImage &out_img, int W=3, int H=3, double sigma=1.0) const
Filter the image with a Gaussian filter with a window size WxH, replacing "this" image by the filtere...
void WriteBuffer(const void *Buffer, size_t Count)
Writes a block of bytes to the stream from Buffer.
void joinImagesHorz(const CImage &im1, const CImage &im2)
Joins two images side-by-side horizontally.
void unload() const noexcept
For external storage image objects only, this method unloads the image from memory (or does nothing i...
float getAsFloat(unsigned int col, unsigned int row, unsigned int channel) const
Returns the contents of a given pixel at the desired channel, in float format: [0,255]->[0,1] The coordinate origin is pixel(0,0)=top-left corner of the image.
#define MRPT_DISABLE_FULL_OPTIMIZATION
mrpt::pimpl< Impl > m_impl
void image_SSSE3_scale_half_3c8u(const uint8_t *in, uint8_t *out, int w, int h, size_t step_in, size_t step_out)
Subsample each 2x2 pixel block into 1x1 pixel, taking the first pixel & ignoring the other 3...
GLubyte GLubyte GLubyte GLubyte w
void swap(CImage &o)
Efficiently swap of two images.
static std::string IMAGES_PATH_BASE(".")
void asCvMat(cv::Mat &out_img, copy_type_t copy_type) const
Makes a shallow or deep copy of this image into the provided cv::Mat.
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
uint64_t getTotalBytesCount() const override
Returns the total size of the internal buffer.
T square(const T x)
Inline function for the square of a number.
void swapRB()
Swaps red and blue channels.
CImage colorImage() const
Returns a color (RGB) version of the grayscale image, or a shallow copy of itself if it is already a ...
mrpt::math::CMatrixDouble33 intrinsicParams
Matrix of intrinsic parameters (containing the focal length and principal point coordinates) ...
#define ASSERT_(f)
Defines an assertion mechanism.
bool loadFromFile(const std::string &fileName, int isColor=-1)
Load image from a file, whose format is determined from the extension (internally uses OpenCV)...
This base provides a set of functions for maths stuff.
static int SERIALIZATION_JPEG_QUALITY_value
RET pixelDepth2IPLCvDepth(PixelDepth d)
size_t getWidth() const override
Returns the width of the image in pixels.
float KLT_response(const unsigned int x, const unsigned int y, const unsigned int half_window_size) const
Compute the KLT response at a given pixel (x,y) - Only for grayscale images (for efficiency it avoids...
void resize(std::size_t width, std::size_t height, TImageChannels nChannels, PixelDepth depth=PixelDepth::D8U)
Changes the size of the image, erasing previous contents (does NOT scale its current content...
mrpt::system::CTimeLogger CTimeLogger
unsigned char * operator()(unsigned int col, unsigned int row, unsigned int channel=0) const
Returns a pointer to a given pixel information.
void normalize(CONTAINER &c, Scalar valMin, Scalar valMax)
Scales all elements such as the minimum & maximum values are shifted to the given values...
virtual void selectTextFont(const std::string &fontName)
Select the current font used when drawing text.
void * getRawBufferData()
Method for getting a pointer to the raw stored data.
This CStream derived class allow using a memory buffer as a CStream.
void internal_fromIPL(const IplImage *iplImage, copy_type_t c)
void saveToStreamAsJPEG(mrpt::io::CStream &out, const int jpeg_quality=95) const
Save image to binary stream as a JPEG (.jpg) compressed format.
void normalize()
Optimize the brightness range of an image without using histogram Only for one channel images...
uint64_t Seek(int64_t Offset, CStream::TSeekOrigin Origin=sFromBeginning) override
Introduces a pure virtual method for moving to a specified position in the streamed resource...
static PixelDepth cvDepth2PixelDepth(int64_t d)
A pair (x,y) of pixel coordinates (integer resolution).
void flipVertical()
Flips the image vertically.
uint8_t * get_unsafe(unsigned int col, unsigned int row, uint8_t channel=0) const
Access to pixels without checking boundaries - Use normally the () operator better, which checks the coordinates.
#define IMPLEMENTS_MEXPLUS_FROM(complete_type)
Structure to hold the parameters of a pinhole camera model.
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
static bool DISABLE_ZIP_COMPRESSION_value
void loadFromStreamAsJPEG(mrpt::io::CStream &in)
Reads the image from a binary stream containing a binary jpeg file.
void rectifyImageInPlace(void *mapX, void *mapY)
Rectify an image (undistorts and rectification) from a stereo pair according to a pair of precomputed...
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
TImageSize getSize() const
Return the size of the image.
GLsizei const GLchar ** string
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
size_type rows() const
Number of rows in the matrix.
size_type cols() const
Number of columns in the matrix.
void clear()
Resets the image to the state after a default ctor.
uint8_t * internal_get(int col, int row, uint8_t channel=0) const
struct mxArray_tag mxArray
Forward declaration for mxArray (avoid #including as much as possible to speed up compiling) ...
CImage grayscale() const
Returns a grayscale version of the image, or a shallow copy of itself if it is already a grayscale im...
void cross_correlation_FFT(const CImage &in_img, math::CMatrixFloat &out_corr, int u_search_ini=-1, int v_search_ini=-1, int u_search_size=-1, int v_search_size=-1, float biasThisImg=0, float biasInImg=0) const
Computes the correlation matrix between this image and another one.
void idft2_complex(const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_real, CMatrixFloat &out_imag)
Compute the 2D inverse Discrete Fourier Transform (DFT).
std::array< double, 5 > dist
[k1 k2 t1 t2 k3] -> k_i: parameters of radial distortion, t_i: parameters of tangential distortion (d...
void setPixel(int x, int y, size_t color) override
Changes the value of the pixel (x,y).
PixelDepth getPixelDepth() const
This class is a "CSerializable" wrapper for "CMatrixFloat".
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void filterMedian(CImage &out_img, int W=3) const
Filter the image with a Median filter with a window size WxW, returning the filtered image in out_img...
CImage()
Default constructor: initialize to empty image.
Virtual base class for "archives": classes abstracting I/O streams.
GLdouble GLdouble GLdouble r
CImage makeDeepCopy() const
Returns a deep copy of this image.
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
TInterpolationMethod
Interpolation methods for images.
bool isOriginTopLeft() const
Returns true (as of MRPT v2.0.0, it's fixed)
struct _IplImage IplImage
virtual mxArray * writeToMatlab() const
Introduces a pure virtual method responsible for writing to a mxArray Matlab object, typically a MATLAB struct whose contents are documented in each derived class.
bool m_imgIsExternalStorage
Set to true only when using setExternalStorage.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Deep copy: the copied object has a duplicate of all data, becoming independent.
GLenum GLenum GLvoid * row
void setSize(size_t row, size_t col, bool zeroNewElements=false)
Changes the size of matrix, maintaining the previous contents.
size_t getRowStride() const
Returns the row stride of the image: this is the number of bytes between two consecutive rows...
void changeSize(uint64_t newSize)
Change size.
CImage scaleDouble(TInterpolationMethod interp) const
Returns a new image scaled up to double its original size.
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
void rotateImage(CImage &out_img, double ang, unsigned int cx, unsigned int cy, double scale=1.0) const
Rotates the image by the given angle around the given center point, with an optional scale factor...
void extract_patch(CImage &patch, const unsigned int col=0, const unsigned int row=0, const unsigned int width=1, const unsigned int height=1) const
Extract a patch from this image, saveing it into "patch" (its previous contents will be overwritten)...
constexpr RET pixelDepth2CvDepth(PixelDepth d)
pimpl< T > make_impl(Args &&... args)
virtual void textOut(int x0, int y0, const std::string &str, const mrpt::img::TColor color)
Renders 2D text using bitmap fonts.
static int interpolationMethod2Cv(TInterpolationMethod i)
void image_SSSE3_bgr_to_gray_8u(const uint8_t *in, uint8_t *out, int w, int h, size_t step_in, size_t step_out)
Convert a RGB image (3cu8) into a GRAYSCALE (1c8u) image, using Y=77*R+150*G+29*B.
bool saveToFile(const std::string &fileName, int jpeg_quality=95) const
Save the image to a file, whose format is determined from the extension (internally uses OpenCV)...
TImageChannels
For use in mrpt::img::CImage.
static int SERIALIZATION_JPEG_QUALITY()
static bool DISABLE_JPEG_COMPRESSION_value
void undistort(CImage &out_img, const mrpt::img::TCamera &cameraParams) const
Undistort the image according to some camera parameters, and returns an output undistorted image...
std::ostream & operator<<(std::ostream &o, const TColor &c)
void compress(void *inData, size_t inDataSize, std::vector< unsigned char > &outData)
Compress an array of bytes into another one.
GLenum GLsizei GLsizei height
void dft2_complex(const CMatrixFloat &in_real, const CMatrixFloat &in_imag, CMatrixFloat &out_real, CMatrixFloat &out_imag)
Compute the 2D Discrete Fourier Transform (DFT) of a complex matrix, returning the real and imaginary...
unsigned __int32 uint32_t
std::string getExternalStorageFileAbsolutePath() const
Only if isExternallyStored() returns true.
This template class provides the basic functionality for a general 2D any-size, resizable container o...
GLsizei GLsizei GLenum GLenum const GLvoid * data
std::string m_externalFile
The file name of a external storage image.
GLenum const GLfloat * params
void clear()
Clear the contents of this container.
static void setImagesPathBase(const std::string &path)
void equalizeHist(CImage &out_img) const
Equalize the image histogram, saving the new image in the given output object.
#define THROW_TYPED_EXCEPTION_FMT(exceptionClass, _FORMAT_STRING,...)
void forceLoad() const
For external storage image objects only, this method makes sure the image is loaded in memory...
static bool loadTGA(const std::string &fileName, mrpt::img::CImage &out_RGB, mrpt::img::CImage &out_alpha)
Loads a TGA true-color RGBA image as two CImage objects, one for the RGB channels plus a separate gra...
static bool my_img_to_grayscale(const cv::Mat &src, cv::Mat &dest)
A class for storing images as grayscale or RGB bitmaps.
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
void loadFromMemoryBuffer(unsigned int width, unsigned int height, bool color, unsigned char *rawpixels, bool swapRedBlue=false)
Reads the image from raw pixels buffer in memory.
Scalar & coeffRef(int r, int c)
static const std::string & getImagesPathBase()
By default, ".".