00001
00002
00003 #ifndef _JAFAR_IMAGE_IMAGE_HPP_
00004 #define _JAFAR_IMAGE_IMAGE_HPP_
00005
00006 #include <fstream>
00007 #include <iostream>
00008
00009 #include <boost/archive/text_oarchive.hpp>
00010 #include <boost/archive/text_iarchive.hpp>
00011 #include "boost/archive/xml_iarchive.hpp"
00012 #include "boost/archive/xml_oarchive.hpp"
00013 #include "boost/archive/binary_iarchive.hpp"
00014 #include "boost/archive/binary_oarchive.hpp"
00015 #include "boost/serialization/split_member.hpp"
00016 #include "boost/serialization/binary_object.hpp"
00017 #include <boost/serialization/string.hpp>
00018 #include "boost/shared_ptr.hpp"
00019
00020 #include <kernel/jafarMacro.hpp>
00021 #include "image/cImage.h"
00022 #include <opencv/cxcore.h>
00023 #if CV_MAJOR_VERSION*10 + CV_MINOR_VERSION > 21
00024 #include <opencv2/core/core.hpp>
00025 #include <opencv2/imgproc/imgproc.hpp>
00026 #include <opencv2/highgui/highgui.hpp>
00027 #include <opencv2/legacy/legacy.hpp>
00028 #else
00029 #include <cxcore.hpp>
00030 #include <cvaux.hpp>
00031 #include <highgui.hpp>
00032 #endif
00033
00034 #ifndef SWIG
00035 namespace cv {
00036 std::ostream& operator<<(std::ostream& os, const cv::Rect &r);
00037 std::ostream& operator<<(std::ostream& os, const cv::Point &p);
00038 std::ostream& operator<<(std::ostream& os, const cv::Size &s);
00039 }
00040 #endif
00041
00042 namespace jafar {
00043
00045 namespace image {
00046 void getQuadrangleSubPix(const cv::Mat& src, cv::Mat& dst, const cv::Mat& mapMatrix);
00047
00048 class Image;
00049 typedef boost::shared_ptr<Image> image_ptr_t;
00050
00055 class Image {
00056
00057 static const int cubicKernelResolution = 255;
00058 static const double cubicKernel1[256];
00059 static const double cubicKernel2[256];
00061 cv::Mat m_matrix;
00062 public:
00063 Image() { }
00064 ~Image();
00075 Image(int width, int height, int depth, JfrImage_TypeColorSpace colorSpace);
00077 Image( Image const & img );
00079 Image& operator=( Image const & img );
00081 Image& operator=( const cv::Mat& matrix );
00083 Image( const CvImage& img );
00085 Image( IplImage* img );
00087 Image( const cv::Mat& matrix );
00090 Image(const Image& img, const cv::Rect& roi);
00091
00093 Image clone() const;
00094
00095
00097 void copyTo(image::Image& dst,
00098 const image::Image& mask = image::Image()) const;
00099
00109 void create( int width, int height, int depth, JfrImage_TypeColorSpace colorSpace );
00110
00127 static Image* loadImage( const char* filename, int iscolor = -1);
00128
00145 bool load( const std::string& filename, int iscolor = -1 );
00146
00152 void save( const std::string& filename) const {
00153
00154 cv::imwrite(filename, m_matrix);
00155 }
00160 void save( const std::string& filename, const std::string& imgname ) {
00161
00162 cv::imwrite(filename, m_matrix);
00163 m_name = imgname;
00164 }
00168 void save( const std::string& filename, const std::vector<int>& params ) {
00169 cv::imwrite(filename, m_matrix, params);
00170 m_name = filename;
00171 };
00172
00173 void print() { JFR_DEBUG(*this); }
00174
00181 void convertColorMode(jafar::image::Image& dst_) const;
00186 void convertDepth(jafar::image::Image& dst_, double scale = 1.0, double offset = 0.0, bool _abs = false) const;
00187
00190 void resize(Image& resizedImage, int interpolation = CV_INTER_LINEAR) const;
00191
00197 Image* resize(double scale, int interpolation = CV_INTER_LINEAR) const;
00198
00205 Image* resize(int newWidth, int newHeight, int interpolation = CV_INTER_LINEAR) const;
00206
00212 void resize(int newWidth, int newHeight, int interpolation = CV_INTER_LINEAR);
00213
00217 int imageSize() const;
00218
00221 inline JfrImage_TypeColorSpace colorSpace() const {
00222 return header.colorSpace;
00223 };
00224 void setColorSpace(JfrImage_TypeColorSpace cs);
00229 inline uchar* data(int line =0) {
00230 return m_matrix.ptr(line);
00231 };
00232
00237 inline const uchar* data(int line =0) const {
00238 return m_matrix.ptr(line);
00239 };
00240
00249 void copy( jafar::image::Image & dst, int x_src = 0, int y_src = 0, int x_dst = 0, int y_dst = 0 , int width = -1, int height = -1) const;
00254 bool robustCopy( jafar::image::Image & dst, int x_src = 0, int y_src = 0, int x_dst = 0, int y_dst = 0 , int width = -1, int height = -1) const;
00255
00256 bool extractPatch(image::Image &dst, int x, int y, int width, int height) const;
00257
00269 cv::Rect getROI() const
00270 {
00271 cv::Size size;
00272 return getROI(size);
00273 }
00278 cv::Rect getROI(cv::Size &size) const
00279 {
00280
00281
00282
00283 cv::Point offset;
00284 m_matrix.locateROI(size, offset);
00285 return cv::Rect(offset.x,offset.y,m_matrix.size().width,m_matrix.size().height);
00286 }
00293 void setROI(const cv::Rect &rect)
00294 {
00295
00296
00297
00298 setROI(rect.x, rect.y, rect.width, rect.height);
00299 }
00303 void setROI(int x, int y, int w, int h)
00304 {
00305
00306 cv::Size size; cv::Point offset;
00307 m_matrix.locateROI(size, offset);
00308 m_matrix.adjustROI(offset.y-y, (h+y)-(m_matrix.size().height+offset.y),
00309 offset.x-x, (w+x)-(m_matrix.size().width +offset.x));
00310 }
00314 void resetROI()
00315 {
00316
00317
00318
00319 cv::Size size; cv::Point offset;
00320 m_matrix.locateROI(size, offset);
00321 m_matrix.adjustROI(offset.y,size.height-(m_matrix.size().height+offset.y),
00322 offset.x,size.width-(m_matrix.size().width+offset.x));
00323 }
00324
00325
00329 inline std::string name() const {
00330 return m_name;
00331 }
00332
00337 void setName(const std::string& _name) {
00338 m_name = _name;
00339 }
00340
00349 template<typename channeltype>
00350 inline channeltype getPixelValue(int x_, int y_, int channel_=0) const;
00351
00364 template<typename channeltype>
00365 double getSubPixelValue(double x_, double y_, int channel_=0, JfrImage_InterpolationType _interpolation = JfrImage_INTERP_BILINEAR) const;
00366
00376 template<typename channeltype>
00377 void setPixelValue(channeltype val_, int x_, int y_, int channel_ = 0);
00378
00383 double computeZncc(Image const* im2) const;
00395 double computeZnccRoisWeight(Image const* im2, cv::Rect const* roi1_ = NULL, cv::Rect const* roi2_ = NULL, float const* weightMatrix = NULL ) const;
00402 double computeZnccRoi(Image const* im2, cv::Rect const* rectRoi) const;
00403
00409 double computeRotatingZncc( Image const* im2, int rotationStep) const;
00410
00415 Image* rankTransform (const int radius);
00416
00423 void rotateScale(double angle, double factor, Image &dest) const;
00424
00428 double orientation(double sigma = 1.5);
00429
00433 bool compHeader(Image const & img) const {
00434 return (width() == img.width() &&
00435 height() == img.height() &&
00436 depth() == img.depth() &&
00437 colorSpace() == img.colorSpace());
00438 }
00440 operator cv::Mat& () { return this->m_matrix; }
00442 operator const cv::Mat& () const { return this->m_matrix; }
00443
00444 #if CV_MAJOR_VERSION*10 + CV_MINOR_VERSION > 22
00445
00446
00447 operator cv::_OutputArray() { return this->m_matrix; }
00448 operator const cv::_OutputArray() const { return const_cast<cv::Mat&>(this->m_matrix); }
00449 #endif
00450
00452 operator const IplImage () const {
00453 return (const IplImage)m_matrix;
00454 }
00456 operator IplImage () {
00457 return (IplImage)m_matrix;
00458 }
00460 operator const CvMat () const { return (const CvMat)m_matrix; }
00462 operator CvMat () { return (CvMat)m_matrix; }
00464 inline cv::Size size() const { return m_matrix.size(); }
00466 inline bool empty() const { return m_matrix.empty(); }
00468 inline int width() const { return m_matrix.cols; }
00470 inline int height() const { return m_matrix.rows; }
00472 inline size_t step() const { return m_matrix.step; }
00474 inline size_t step1() const { return m_matrix.step1(); }
00476 inline int depth() const { return m_matrix.depth(); }
00478 inline int channels() const { return m_matrix.channels(); }
00480 inline int type() const { return m_matrix.type(); }
00482 inline cv::Mat mat() const { return m_matrix; }
00484 inline void detach() { m_matrix.release(); }
00486 inline size_t pix_size() { return !m_matrix.empty() ? m_matrix.elemSize() : 0; }
00488 void setTo(const cv::Scalar& s, const image::Image& mask=image::Image()) {
00489 m_matrix.setTo(s, mask);
00490 }
00492 void convertTo(image::Image& dst, double alpha=1, double beta=0) const {
00493 m_matrix.convertTo(dst, dst.type(), alpha, beta);
00494 }
00495
00496 private:
00497
00498 void initImageHeader();
00499
00500 friend class boost::serialization::access;
00501
00502 template<class Archive>
00503 void save(Archive & ar, const unsigned int version) const {
00504 JFR_PRECOND(!m_matrix.empty(), "Nothing to save");
00505 IplImage image = (IplImage)m_matrix;
00506 ar << boost::serialization::make_nvp("width",image.width);
00507 ar << boost::serialization::make_nvp("height",image.height);
00508 ar << boost::serialization::make_nvp("depth",image.depth);
00509 ar << boost::serialization::make_nvp("colorSpace",header.colorSpace);
00510 ar << boost::serialization::make_nvp("nChannels",image.nChannels);
00511 ar << boost::serialization::make_nvp("nSize",image.nSize);
00512 ar << boost::serialization::make_nvp("ID",image.ID);
00513 ar << boost::serialization::make_nvp("dataOrder",image.dataOrder);
00514 ar << boost::serialization::make_nvp("origin",image.origin);
00515 ar << boost::serialization::make_nvp("imageSize",image.imageSize);
00516 ar << boost::serialization::make_nvp("pixeldata", boost::serialization::make_binary_object(image.imageData, image.imageSize));
00517 ar << boost::serialization::make_nvp("widthStep",image.widthStep);
00518 }
00519
00520 template<class Archive>
00521 void load(Archive & ar, const unsigned int version) {
00522 int width, height, depth;
00523 JfrImage_TypeColorSpace cs;
00524 ar >> boost::serialization::make_nvp("width",width);
00525 ar >> boost::serialization::make_nvp("height",height);
00526 ar >> boost::serialization::make_nvp("depth",depth);
00527 ar >> boost::serialization::make_nvp("colorSpace",cs);
00528 create(width, height, depth, cs);
00529 IplImage image = (IplImage)m_matrix;
00530 ar >> boost::serialization::make_nvp("nChannels",image.nChannels);
00531 ar >> boost::serialization::make_nvp("nSize",image.nSize);
00532 ar >> boost::serialization::make_nvp("ID",image.ID);
00533 ar >> boost::serialization::make_nvp("dataOrder",image.dataOrder);
00534 ar >> boost::serialization::make_nvp("origin",image.origin);
00535 ar >> boost::serialization::make_nvp("imageSize",image.imageSize);
00536 ar >> boost::serialization::make_nvp("pixeldata", boost::serialization::make_binary_object(image.imageData, image.imageSize));
00537 ar >> boost::serialization::make_nvp("widthStep",image.widthStep);
00538 memset(image.BorderMode, 0, 4);
00539 memset(image.BorderConst, 0, 4);
00540 image.imageDataOrigin = image.imageData;
00541 }
00542 #ifndef SWIG
00543 BOOST_SERIALIZATION_SPLIT_MEMBER()
00544 #endif
00545
00546 private:
00552 inline double cubicKernel( int t, double dt ) const;
00553 inline double cubicKernelI( int t, int idx ) const;
00554 private:
00555 JfrImage_ImageHeader header;
00556
00557 std::string m_name;
00558 };
00559
00560 template<typename channeltype>
00561 channeltype Image::getPixelValue(int x_, int y_, int channel_) const {
00562 JFR_PRECOND(x_ >= 0 && y_ >= 0 && x_ < width() && y_ < height(), "JfrImage::pixelValue pixel coordinates are not in the image.");
00563 JFR_PRECOND( 0 <= channel_ && channel_ < channels(), "JfrImage::pixelValue wrong channel parameter ");
00564 channeltype const *pxPtr;
00565 pxPtr = reinterpret_cast<channeltype const *>(data(y_));
00566 return *(pxPtr + x_*channels() + channel_);
00567 }
00568
00569 inline double Image::cubicKernelI( int _t, int _idx ) const
00570 {
00571 switch( _t )
00572 {
00573 case -1:
00574 return cubicKernel2[_idx];
00575 case 0:
00576 return cubicKernel1[_idx];
00577 case 1:
00578 return cubicKernel1[cubicKernelResolution - _idx];
00579 case 2:
00580 return cubicKernel2[cubicKernelResolution - _idx];
00581 }
00582 return 0;
00583 }
00584 inline double Image::cubicKernel( int _t, double _dt ) const
00585 {
00586 int idx =int (_dt * cubicKernelResolution );
00587 return cubicKernelI( _t, idx );
00588 }
00589
00590 template<typename channeltype>
00591 double Image::getSubPixelValue(double x_, double y_, int channel_, JfrImage_InterpolationType _interpolation ) const {
00592 int height_ = height();
00593 int width_ = width();
00594 JFR_PRECOND(x_ >= 0. && y_ >= 0. && x_ <= (double)width_ - 1 && y_ <= (double)height_ - 1,
00595 "JfrImage::pixelValue pixel coordinates are not in the image.");
00596 JFR_PRECOND( 0 <= channel_ && channel_ < channels(), "JfrImage::getSubpixelValue wrong channel parameter ");
00597 if( x_ == width() - 1) x_ -= 1e-6;
00598 if( y_ == height() - 1) y_ -= 1e-6;
00599
00600 switch( _interpolation )
00601 {
00602 case JfrImage_INTERP_NEAREST:
00603 {
00604 return getPixelValue<channeltype>( lrint( x_ ), lrint( y_ ), channel_ );
00605 }
00606 case JfrImage_INTERP_BILINEAR:
00607 {
00608 int xi = (int)floor(x_);
00609 int yi = (int)floor(y_);
00610
00611 double dx = x_-floor(x_);
00612 double dy = y_-floor(y_);
00613 double c11 = (1-dx)*(1-dy);
00614 double c12 = (1-dy)*dx;
00615 double c21 = (1-dx)*dy;
00616 double c22 = dx*dy;
00617
00618 return (
00619 c11 * getPixelValue<channeltype>(xi,yi, channel_)
00620 + c12 * getPixelValue<channeltype>(xi+1,yi, channel_)
00621 + c21 * getPixelValue<channeltype>(xi,yi+1, channel_)
00622 + c22 * getPixelValue<channeltype>(xi+1,yi+1, channel_));
00623 }
00624 case JfrImage_INTERP_CUBIC:
00625 {
00626 double result = 0.0;
00627 int xi = int(x_);
00628 int yi = int(y_);
00629 double dx = x_ - xi;
00630 int idxX =int( dx * cubicKernelResolution );
00631 double dy = y_ - yi;
00632 int idxY =int( dy * cubicKernelResolution );
00633 int channelsCount = channels();
00634 int offset = (xi - 1) * channelsCount + channel_;
00635 for(int v = -1; v < 3; ++v)
00636 {
00637 int yt = yi + v;
00638 if( yt >= 0 and yt < height_ )
00639 {
00640 channeltype const *pxPtr = reinterpret_cast<channeltype const *>(data(yt));
00641 pxPtr += offset;
00642
00643 double ycoef = cubicKernelI( v, idxY);
00644 for(int u = -1; u < 3; ++u, pxPtr += channelsCount)
00645 {
00646 int xt = xi + u;
00647 if( xt >= 0 and xt < width_ )
00648 {
00649 result += ycoef * cubicKernelI( u, idxX ) * *pxPtr;
00650 }
00651 }
00652 }
00653 }
00654 return result;
00655 }
00656 }
00657 return -1;
00658 }
00659
00660 template<typename channeltype>
00661 void Image::setPixelValue(channeltype val_, int x_, int y_, int channel_) {
00662 JFR_PRECOND(x_ >= 0 && y_ >= 0 && x_ < width() && y_ < height(),
00663 "JfrImage::pixelValue pixel coordinates are not in the image.");
00664 JFR_PRECOND( 0 <= channel_ && channel_ < channels(), "JfrImage::pixelValue "
00665 "wrong channel parameter ");
00666 channeltype *pxPtr = reinterpret_cast<channeltype*>(data(y_));
00667 *(pxPtr+ x_ * channels() + channel_) = val_;
00668 }
00669
00670 std::ostream& operator<<(std::ostream& s, const Image& image);
00671 std::ostream& operator<<(std::ostream& s, const JfrImage_TypeColorSpace tcs);
00672
00682 class ImageIO {
00683 public:
00684 static void xml_load(jafar::image::Image & img, std::string const & filename);
00685 static void xml_save(jafar::image::Image & img, std::string const & filename);
00686 static void bin_load(jafar::image::Image & img, std::string const & filename);
00687 static void bin_save(jafar::image::Image & img, std::string const & filename);
00688 private:
00689 ImageIO() {};
00690 };
00691
00692 }
00693 }
00694
00695 #endif