#ifdef __cplusplus extern c #endif 的作用

其实很简单,作用就是
如果此头文件是在c++中使用的(就是一个.cpp文件include此头文件,而不是一个.c文件),
那么函数名称粉碎方式仍然使用C中的方式。(就是此函数编译后在object文件中的内部名称和C中是兼容的)

比如
void foo1();
如果c文件包含了它,生成的object文件中此函数被命名为 c_foo1,
而在cpp文件中包含了它,生成的object中此函数命名为cpp_foo1,使用extern "C"后,可以强制使其仍然为"c_foo1"。

这么做的目的是为了在c和cpp中互相调用函数命名一致,否则会出现链接错误。

/*****************************************************************************
*   ImageUtils
*   Handy utility functions for dealing with images in OpenCV (desktop or Android).
*   The most recent version of this will always be available from "http://shervinemami.info/openCV.html"
******************************************************************************
*   by Shervin Emami, 5th Dec 2012 ([email protected])
*   http://www.shervinemami.info/
******************************************************************************
*   Ch1 of the book "Mastering OpenCV with Practical Computer Vision Projects"
*   Copyright Packt Publishing 2012.
*   http://www.packtpub.com/cool-projects-with-opencv/book
*****************************************************************************/

#ifndef IMAGEUTILS_0_7_H_
#define IMAGEUTILS_0_7_H_


// OpenCV
#include <cv.h>
//#include <cvaux.h>
#include <cxcore.h>
#ifdef USE_HIGHGUI
    #include <highgui.h>
#endif


#include <stdio.h>
#if defined WIN32 || defined _WIN32
    #include <conio.h>        // For _kbhit() on Windows
    #include <direct.h>        // For mkdir(path) on Windows
    #define snprintf sprintf_s    // Visual Studio on Windows comes with sprintf_s() instead of snprintf()
#else
    #include <stdio.h>        // For getchar() on Linux
    #include <termios.h>    // For kbhit() on Linux
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>    // For mkdir(path, options) on Linux
#endif
#include <vector>
#include <string>
#include <iostream>            // for printing streams in C++
//#include <stdarg.h>        // for variable-length args in C
//#include <sstream>        // for printing floats in C++
//#include <fstream>        // for opening files in C++

// These functions will print using the LOG() function, using the same format as printf(). If you want it to be printed using a different
// function (such as for Android logcat output), then define LOG as your output function, otherwise it will use printf() by default.
#ifndef LOG
    #ifdef __ANDROID__
        // For Android debug logging to logcat:
        #include <android/log.h>
        #define LOG(fmt, args...) (__android_log_print(ANDROID_LOG_INFO, "........", fmt, ## args))
    #else
        // For stdout debug logging, with a new-line character on the end:
        #ifndef _MSC_VER
            // Compiles on GCC but not MSVC:
            #define LOG(fmt, args...) do {printf(fmt, ## args); printf("\n"); fflush(stdout);} while (0)
    //        #define LOG printf
        #else
            #define LOG printf
        #endif
    #endif
#endif


#ifdef __cplusplus
extern "C"
{
#endif


// Allow 'UCHAR' variables in both C and C++ code.
#ifndef UCHAR
    typedef unsigned char UCHAR;
#endif

// Allow 'bool' variables in both C and C++ code.
#ifndef __cplusplus
    typedef int bool;
    #define true (1)
    #define false (0)
#endif

// Allow default args in C++ code, but explicit args in C code.
#ifdef __cplusplus
    #define DEFAULT(val) = val
#else
    #define DEFAULT(val)
#endif



//------------------------------------------------------------------------------
// Timer functions
//------------------------------------------------------------------------------
// Record the execution time of some code, in milliseconds. By Shervin Emami, 27th May 2012.
// eg:
//  DECLARE_TIMING(myTimer);
//    ...
//  START_TIMING(myTimer);
//    printf("A slow calc = %f\n", pow(1.2, 3.4) );
//  STOP_TIMING(myTimer);
//  AVERAGE_TIMING(myTimer);
#define DECLARE_TIMING(s)           int64 timeStart_##s; int64 timeDiff_##s; int64 timeTally_##s = 0; int64 countTally_##s = 0; double timeMin_##s = DBL_MAX; double timeMax_##s = 0; int64 timeEnd_##s;
#define START_TIMING(s)             timeStart_##s = cvGetTickCount()
#define STOP_TIMING(s)              do {    timeEnd_##s = cvGetTickCount(); timeDiff_##s = (timeEnd_##s - timeStart_##s); timeTally_##s += timeDiff_##s; countTally_##s++; timeMin_##s = MIN(timeMin_##s, timeDiff_##s); timeMax_##s = MAX(timeMax_##s, timeDiff_##s);    } while (0)
#define GET_TIMING(s)               (double)(0.001 * ( (double)timeDiff_##s / (double)cvGetTickFrequency() ))
#define GET_MIN_TIMING(s)           (double)(0.001 * ( (double)timeMin_##s / (double)cvGetTickFrequency() ))
#define GET_MAX_TIMING(s)           (double)(0.001 * ( (double)timeMax_##s / (double)cvGetTickFrequency() ))
#define GET_AVERAGE_TIMING(s)       (double)(countTally_##s ? 0.001 * ( (double)timeTally_##s / ((double)countTally_##s * cvGetTickFrequency()) ) : 0)
#define GET_TOTAL_TIMING(s)         (double)(0.001 * ( (double)timeTally_##s / ((double)cvGetTickFrequency()) ))
#define GET_TIMING_COUNT(s)         (int)(countTally_##s)
#define CLEAR_AVERAGE_TIMING(s)     do {    timeTally_##s = 0; countTally_##s = 0;     } while (0)
#define SHOW_TIMING(s, msg)         LOG("%s time:\t %dms\t (ave=%dms min=%dms max=%dms, across %d runs).", msg, cvRound(GET_TIMING(s)), cvRound(GET_AVERAGE_TIMING(s)), cvRound(GET_MIN_TIMING(s)), cvRound(GET_MAX_TIMING(s)), GET_TIMING_COUNT(s) )
#define SHOW_TOTAL_TIMING(s, msg)   LOG("%s total:\t %dms\t (ave=%dms min=%dms max=%dms, across %d runs).", msg, cvRound(GET_TOTAL_TIMING(s)), cvRound(GET_AVERAGE_TIMING(s)), cvRound(GET_MIN_TIMING(s)), cvRound(GET_MAX_TIMING(s)), GET_TIMING_COUNT(s) )
#define AVERAGE_TIMING(s)           SHOW_TIMING(s, #s)
#define TOTAL_TIMING(s)             do {    SHOW_TOTAL_TIMING(s, #s); CLEAR_AVERAGE_TIMING(s);     } while (0)


// Convert a float number to an int by rounding to nearest int using a certain method.
// Replace the code with the fastest method detected by 'testTiming_FloatConversion()'.
inline int roundFloat(float f);

//------------------------------------------------------------------------------
// Graphing functions
//------------------------------------------------------------------------------

// Draw the graph of an array of floats into imageDst or a new image, between minV & maxV if given.
// Remember to free the newly created image if imageDst is not given.
IplImage* drawFloatGraph(const float *arraySrc, int nArrayLength, IplImage *imageDst DEFAULT(0), float minV DEFAULT(0.0), float maxV DEFAULT(0.0), int width DEFAULT(0), int height DEFAULT(0), char *graphLabel DEFAULT(0), bool showScale DEFAULT(true));

// Draw the graph of an array of ints into imageDst or a new image, between minV & maxV if given.
// Remember to free the newly created image if imageDst is not given.
IplImage* drawIntGraph(const int *arraySrc, int nArrayLength, IplImage *imageDst DEFAULT(0), int minV DEFAULT(0), int maxV DEFAULT(0), int width DEFAULT(0), int height DEFAULT(0), char *graphLabel DEFAULT(0), bool showScale DEFAULT(true));

// Draw the graph of an array of uchars into imageDst or a new image, between minV & maxV if given.
// Remember to free the newly created image if imageDst is not given.
IplImage* drawUCharGraph(const uchar *arraySrc, int nArrayLength, IplImage *imageDst DEFAULT(0), int minV DEFAULT(0), int maxV DEFAULT(0), int width DEFAULT(0), int height DEFAULT(0), char *graphLabel DEFAULT(0), bool showScale DEFAULT(true));

// Display a graph of the given float array.
// If background is provided, it will be drawn into, for combining multiple graphs using drawFloatGraph().
// Set delay_ms to 0 if you want to wait forever until a keypress, or set it to 1 if you want it to delay just 1 millisecond.
void showFloatGraph(const char *name, const float *arraySrc, int nArrayLength, int delay_ms DEFAULT(500), IplImage *background DEFAULT(0));

// Display a graph of the given int array.
// If background is provided, it will be drawn into, for combining multiple graphs using drawIntGraph().
// Set delay_ms to 0 if you want to wait forever until a keypress, or set it to 1 if you want it to delay just 1 millisecond.
void showIntGraph(const char *name, const int *arraySrc, int nArrayLength, int delay_ms DEFAULT(500), IplImage *background DEFAULT(0));

// Display a graph of the given unsigned char array.
// If background is provided, it will be drawn into, for combining multiple graphs using drawUCharGraph().
// Set delay_ms to 0 if you want to wait forever until a keypress, or set it to 1 if you want it to delay just 1 millisecond.
void showUCharGraph(const char *name, const uchar *arraySrc, int nArrayLength, int delay_ms DEFAULT(500), IplImage *background DEFAULT(0));

// Simple helper function to easily view an image, with an optional pause.
void showImage(const IplImage *img, int delay_ms DEFAULT(0), char *name DEFAULT(0));

// Call 'setGraphColor(0)' to reset the colors that will be used for graphs.
void setGraphColor(int index DEFAULT(0));
// Specify the exact color that the next graph should be drawn as.
void setCustomGraphColor(int R, int B, int G);

//------------------------------------------------------------------------------
// Color conversion functions
//------------------------------------------------------------------------------

// Return a new image that is always greyscale, whether the input image was RGB or Greyscale.
// Remember to free the returned image using cvReleaseImage() when finished.
IplImage* convertImageToGreyscale(const IplImage *imageSrc);

// Create an RGB image from the YIQ image using an approximation of NTSC conversion(ref: "YIQ" Wikipedia page).
// Remember to free the generated RGB image.
IplImage* convertImageYIQtoRGB(const IplImage *imageYIQ);

// Create a YIQ image from the RGB image using an approximation of NTSC conversion(ref: "YIQ" Wikipedia page).
// Remember to free the generated YIQ image.
IplImage* convertImageRGBtoYIQ(const IplImage *imageRGB);

// Create an RGB image from the HSV image using the full 8-bits, since OpenCV only allows Hues up to 180 instead of 255.
// ref: "http://cs.haifa.ac.il/hagit/courses/ist/Lectures/Demos/ColorApplet2/t_convert.html"
// Remember to free the generated RGB image.
IplImage* convertImageHSVtoRGB(const IplImage *imageHSV);

// Create a HSV image from the RGB image using the full 8-bits, since OpenCV only allows Hues up to 180 instead of 255.
// ref: "http://cs.haifa.ac.il/hagit/courses/ist/Lectures/Demos/ColorApplet2/t_convert.html"
// Remember to free the generated HSV image.
IplImage* convertImageRGBtoHSV(const IplImage *imageRGB);

// Do the color conversion of a single pixel, from RGB to HSV using Hue values between 0 to 255, whereas OpenCV only allows Hues up to 180 instead of 255.
// ref: "http://cs.haifa.ac.il/hagit/courses/ist/Lectures/Demos/ColorApplet2/t_convert.html"
inline void convertPixelRGBtoHSV_256(int bR, int bG, int bB, int &bH, int &bS, int &bV);
// Do the color conversion of a single pixel, from HSV to RGB using Hue values between 0 to 255, whereas OpenCV only allows Hues up to 180 instead of 255.
// ref: "http://cs.haifa.ac.il/hagit/courses/ist/Lectures/Demos/ColorApplet2/t_convert.html"
inline void convertPixelHSVtoRGB_256(int bH, int bS, int bV, int &bR, int &bG, int &bB);

// Do the color conversion of a single pixel, from RGB to HSV using Hue values between 0 to 179 just like OpenCV does, instead of Hues upto 255.
void convertPixelRGBtoHSV_180(int bR, int bG, int bB, int &bH, int &bS, int &bV);
// Do the color conversion of a single pixel, from HSV to RGB using Hue values between 0 to 179 just like OpenCV does, instead of Hues upto 255.
void convertPixelHSVtoRGB_180(int bH, int bS, int bV, int &bR, int &bG, int &bB);

//------------------------------------------------------------------------------
// 2D Point functions
//------------------------------------------------------------------------------
// Return (pointA + pointB).
CvPoint2D32f addPointF(const CvPoint2D32f pointA, const CvPoint2D32f pointB);
// Return (pointA - pointB).
CvPoint2D32f subtractPointF(const CvPoint2D32f pointA, const CvPoint2D32f pointB);

// Return (point * scale).
CvPoint2D32f scalePointF(const CvPoint2D32f point, float scale);
// Return the point scaled relative to the given origin.
CvPoint2D32f scalePointAroundPointF(const CvPoint2D32f point, const CvPoint2D32f origin, float scale);

// Return (p * s), to a maximum value of maxVal
float scaleValueF(float p, float s, float maxVal);
#define scaleValueFI(p, s, maxVal) scaleValueF(p, s, (float)maxVal)
// Return (p * s), to a maximum value of maxVal
int scaleValueI(int p, float s, int maxVal);

// Return the point rotated around its origin by angle (in degrees).
CvPoint2D32f rotatePointF(const CvPoint2D32f point, float angleDegrees);
// Return the point rotated around the given origin by angle (in degrees).
CvPoint2D32f rotatePointAroundPointF(const CvPoint2D32f point, const CvPoint2D32f origin, float angleDegrees);

// Calculate the distance between the 2 given (floating-point) points.
float findDistanceBetweenPointsF(const CvPoint2D32f p1, const CvPoint2D32f p2);
// Calculate the distance between the 2 given (integer) points.
float findDistanceBetweenPointsI(const CvPoint p1, const CvPoint p2);

// Calculate the angle between the 2 given integer points (in degrees).
float findAngleBetweenPointsF(const CvPoint2D32f p1, const CvPoint2D32f p2);
// Calculate the angle between the 2 given floating-point points (in degrees).
float findAngleBetweenPointsI(const CvPoint p1, const CvPoint p2);

// Draw a crossbar at the given position.
void drawCross(IplImage *img, const CvPoint pt, int radius, const CvScalar color );

// Print the label and then the rect to the console for easy debugging
void printPoint(const CvPoint pt, const char *label);
// Print the label and then the rect to the console for easy debugging
void printPointF(const CvPoint2D32f pt, const char *label);


//------------------------------------------------------------------------------
// Rectangle region functions
//------------------------------------------------------------------------------

// Enlarge or shrink the rectangle size & center by a given scale.
// If w & h are given, will make sure the rectangle stays within the bounds if it is enlarged too much.
// Note that for images, w should be (width-1) and h should be (height-1).
CvRect scaleRect(const CvRect rectIn, float scaleX, float scaleY, int w DEFAULT(0), int h DEFAULT(0));

// Enlarge or shrink the rectangle region by a given scale without moving its center, and possibly add a border around it.
// If w & h are given, will make sure the rectangle stays within the bounds if it is enlarged too much.
// Note that for images, w should be (width-1) and h should be (height-1).
CvRect scaleRectInPlace(const CvRect rectIn, float scaleX, float scaleY, float borderX DEFAULT(0.0f), float borderY DEFAULT(0.0f), int w DEFAULT(0), int h DEFAULT(0));

// Return a new rect that the same as rectA when shifted by (rectB.x, rectB.y).
CvRect offsetRect(const CvRect rectA, const CvRect rectB);
// Return a new rect that the same as rectA when shifted by (pt.x, pt.y).
CvRect offsetRectPt(const CvRect rectA, const CvPoint pt);

// Draw a rectangle around the given object. (Use CV_RGB(255,0,0) for red color)
void drawRect(IplImage *img, const CvRect rect, const CvScalar color DEFAULT(CV_RGB(220,0,0)));
// Draw a filled rectangle around the given object.
void drawRectFilled(IplImage *img, const CvRect rect, const CvScalar color DEFAULT(CV_RGB(220,0,0)));

// Print the label and then the rectangle information to the console for easy debugging
void printRect(const CvRect rect, const char *label DEFAULT(0));

// Make sure the given rectangle is completely within the given image dimensions.
CvRect cropRect(const CvRect rectIn, int w, int h);

//------------------------------------------------------------------------------
// Image transforming functions
//------------------------------------------------------------------------------

// Returns a new image that is a cropped version of the original image.
// Remember to free the new image later.
IplImage* cropImage(const IplImage *img, const CvRect region);

// Creates a new image copy that is of a desired size. The aspect ratio will be kept constant if desired, by cropping the desired region.
// Remember to free the new image later.
IplImage* resizeImage(const IplImage *origImg, int newWidth, int newHeight, bool keepAspectRatio);

// Rotate the image clockwise and possibly scale the image. Use 'mapRotatedImagePoint()' to map pixels from the src to dst image.
IplImage *rotateImage(const IplImage *src, float angleDegrees, float scale DEFAULT(1.0f));

// Get the position of a pixel in the image after the rotateImage() operation.
CvPoint2D32f mapRotatedImagePoint(const CvPoint2D32f pointOrig, const IplImage *image, float angleRadians, float scale DEFAULT(1.0f));

//------------------------------------------------------------------------------
// Image utility functions
//------------------------------------------------------------------------------

// Paste multiple images next to each other as a single image, for saving or displaying.
// Remember to free the returned image.
// Sample usage: cvSaveImage("out.png", combineImages(2, img1, img2) );
// Modified by Shervin from the cvShowManyImages() function on the OpenCVWiki by Parameswaran.
// 'combineImagesResized()' will resize all images to 300x300, whereas 'combineImages()' doesn't resize the images at all.
IplImage* combineImagesResized(int nArgs, ...);
IplImage* combineImages(int nArgs, ...);

// Do Bilateral Filtering to smooth the image noise but preserve the edges.
// A smoothness of 5 is very little filtering, and 100 is very high filtering.
// Remember to free the returned image.
IplImage* smoothImageBilateral(const IplImage *src, float smoothness DEFAULT(30));

// Blend color images 'image1' and 'image2' using an 8-bit alpha-blending mask channel.
// Equivalent to this operation on each pixel: imageOut = image1 * (1-(imageAlphaMask/255)) + image2 * (imageAlphaMask/255)
// So if a pixel in imageAlphMask is 0, then that pixel in imageOut will be image1, or if imageAlphaMask is 255 then imageOut is image2,
// or if imageAlphaMask was 200 then imageOut would be: image1 * 0.78 + image2 * 0.22
// Returns a new image, so remember to call 'cvReleaseImage()' on the result.
IplImage* blendImage(const IplImage* image1, const IplImage* image2, const IplImage* imageAlphaMask);

// Get an 8-bit equivalent of the 32-bit Float Matrix.
// Returns a new image, so remember to call 'cvReleaseImage()' on the result.
IplImage* convertMatrixToUcharImage(const CvMat *srcMat);

// Get a normal 8-bit uchar image equivalent of the 32-bit float greyscale image.
// Returns a new image, so remember to call 'cvReleaseImage()' on the result.
IplImage* convertFloatImageToUcharImage(const IplImage *srcImg);

// Save the given image to a JPG or BMP file, even if its format isn't an 8-bit image, such as a 32bit image.
int saveImage(const char *filename, const IplImage *image);

// Store a greyscale floating-point CvMat image into a BMP/JPG/GIF/PNG image,
// since cvSaveImage() can only handle 8bit images (not 32bit float images).
void saveFloatMat(const char *filename, const CvMat *src);

// Store a greyscale floating-point CvMat image into a BMP/JPG/GIF/PNG image,
// since cvSaveImage() can only handle 8bit images (not 32bit float images).
void saveFloatImage(const char *filename, const IplImage *srcImg);

// Draw some text onto an image using printf() format.
void drawText(IplImage *img, CvPoint position, CvScalar color, char *fmt, ...);

// Print the label and then some text info about the IplImage properties, to LOG() for easy debugging.
void printImageInfo(const IplImage *image_tile, const char *label DEFAULT(0));
// Print the pixel values of the IplImage, to LOG() for easy debugging. maxElements of 0 will print all the data.
void printImagePixels(const IplImage *image, const char *label DEFAULT(0), int maxElements DEFAULT(300));
// Print the label and then contents of a cv::Mat from the C++ interface (using "LOG()") for easy debugging.
void printMat(const cv::Mat M, const char *label DEFAULT(0), int maxElements DEFAULT(300));
// Print the label and then contents of the Matrix (using "LOG()") for easy debugging. maxElements of 0 will print all the data.
void printMatrix(const CvMat *M, const char *label DEFAULT(0), int maxElements DEFAULT(300));
// Print the label and info of a cv::Mat from the C++ interface (using "LOG()") for easy debugging.
void printMatInfo(const cv::Mat M, const char *label DEFAULT(0));
// Print the x & y coords of the given point. If 'label' is supplied, prints that first, and also prints a newline character on the end.
void printPoint32f(const CvPoint2D32f pt, const char *label DEFAULT(0));
// Print the start & end coords of the given line. If 'label' is supplied, prints that first, and also prints a newline character on the end.
void printLine(const CvPoint ptA, const CvPoint ptB, const char *label DEFAULT(0));
// Just for debugging float images & matrices.
void printDataRange(const CvArr *src, const char *msg);



#if defined (__cplusplus)
}
#endif


#endif /* IMAGEUTILS_H_ */


你可能感兴趣的:(#ifdef __cplusplus extern c #endif 的作用)