├── README.md ├── testScan.v11.suo ├── testScan.v12.suo ├── testScan ├── MX500IPL.cpp ├── MX500IPL.h ├── cvScanProCam.cpp ├── cvCalibrateProCam.cpp ├── cvStructuredLight.cpp ├── DVP_SDK │ ├── Lib │ │ └── DVP_CAMSDK.lib │ └── Include │ │ ├── DVP_CamAPI.h │ │ ├── DVP_Define.h │ │ └── DVP_Paramdef.h ├── stdafx.cpp ├── stdafx.h ├── cvScanProCam.h ├── testScan.vcxproj.filters ├── config.xml ├── cvUtilProCam.h ├── cvCalibrateProCam.h ├── testScan.vcxproj ├── cvStructuredLight.h └── cvUtilProCam.cpp └── testScan.sln /README.md: -------------------------------------------------------------------------------- 1 | # Easy3DScanner 2 | 3D结构光扫描仪,物电学院,第四届光电设计竞赛,光栅投影,格雷码 3 | -------------------------------------------------------------------------------- /testScan.v11.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liurongfang/Easy3DScanner/HEAD/testScan.v11.suo -------------------------------------------------------------------------------- /testScan.v12.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liurongfang/Easy3DScanner/HEAD/testScan.v12.suo -------------------------------------------------------------------------------- /testScan/MX500IPL.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liurongfang/Easy3DScanner/HEAD/testScan/MX500IPL.cpp -------------------------------------------------------------------------------- /testScan/MX500IPL.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liurongfang/Easy3DScanner/HEAD/testScan/MX500IPL.h -------------------------------------------------------------------------------- /testScan/cvScanProCam.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liurongfang/Easy3DScanner/HEAD/testScan/cvScanProCam.cpp -------------------------------------------------------------------------------- /testScan/cvCalibrateProCam.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liurongfang/Easy3DScanner/HEAD/testScan/cvCalibrateProCam.cpp -------------------------------------------------------------------------------- /testScan/cvStructuredLight.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liurongfang/Easy3DScanner/HEAD/testScan/cvStructuredLight.cpp -------------------------------------------------------------------------------- /testScan/DVP_SDK/Lib/DVP_CAMSDK.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liurongfang/Easy3DScanner/HEAD/testScan/DVP_SDK/Lib/DVP_CAMSDK.lib -------------------------------------------------------------------------------- /testScan/DVP_SDK/Include/DVP_CamAPI.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liurongfang/Easy3DScanner/HEAD/testScan/DVP_SDK/Include/DVP_CamAPI.h -------------------------------------------------------------------------------- /testScan/DVP_SDK/Include/DVP_Define.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liurongfang/Easy3DScanner/HEAD/testScan/DVP_SDK/Include/DVP_Define.h -------------------------------------------------------------------------------- /testScan/DVP_SDK/Include/DVP_Paramdef.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liurongfang/Easy3DScanner/HEAD/testScan/DVP_SDK/Include/DVP_Paramdef.h -------------------------------------------------------------------------------- /testScan/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp: Source file that includes just the standard items. 2 | // 3 | // Overview: 4 | // This is the source file included by default in Visual Studio 2005. 5 | // Note that stdafx.obj will contain pre-compiled type information. 6 | // 7 | // Details: 8 | // Please read the SIGGRAPH 2009 course notes for additional details. 9 | // 10 | // Douglas Lanman and Gabriel Taubin 11 | // "Build Your Own 3D Scanner: 3D Photography for Beginners" 12 | // ACM SIGGRAPH 2009 Course Notes 13 | // 14 | // Author: 15 | // Douglas Lanman 16 | // Brown University 17 | // July 2009 18 | 19 | #include "stdafx.h" -------------------------------------------------------------------------------- /testScan/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h: Header file for standard system include files. 2 | // 3 | // Overview: 4 | // This is the header file included by default in Visual Studio 2005. 5 | // 6 | // Details: 7 | // Please read the SIGGRAPH 2009 course notes for additional details. 8 | // 9 | // Douglas Lanman and Gabriel Taubin 10 | // "Build Your Own 3D Scanner: 3D Photography for Beginners" 11 | // ACM SIGGRAPH 2009 Course Notes 12 | // 13 | // Author: 14 | // Douglas Lanman 15 | // Brown University 16 | // July 2009 17 | 18 | #pragma once 19 | 20 | // Exclude rarely-used items from Windows headers. 21 | #define WIN32_LEAN_AND_MEAN 22 | 23 | // Define commonly included files. 24 | #include 25 | #include 26 | #include "opencv/cv.h" 27 | #include "opencv/highgui.h" 28 | #include "MX500IPL.h" 29 | #include 30 | #include 31 | #include 32 | #include -------------------------------------------------------------------------------- /testScan.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testScan", "testScan\testScan.vcxproj", "{10822151-18C9-4ED4-AE56-C9C79C5DB9D4}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {10822151-18C9-4ED4-AE56-C9C79C5DB9D4}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {10822151-18C9-4ED4-AE56-C9C79C5DB9D4}.Debug|Win32.Build.0 = Debug|Win32 14 | {10822151-18C9-4ED4-AE56-C9C79C5DB9D4}.Release|Win32.ActiveCfg = Release|Win32 15 | {10822151-18C9-4ED4-AE56-C9C79C5DB9D4}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /testScan/cvScanProCam.h: -------------------------------------------------------------------------------- 1 | // cvScanProCam.h: Header file for structured light scanning. 2 | // 3 | // Overview: 4 | // This file defines the functions for structured light scanning. The current implementation 5 | // supports a single projector-camera pair. The projector-camera system must be calibrated 6 | // prior to running the scanning function. A 3D point cloud and depth map are recovered by 7 | // optical triangulation. Three scanning modes are implemented, including: (1) encoding only 8 | // the projector columns, (2) encoding only the projector rows, (3) encoding both rows and 9 | // columns. Two reconstruction methods are implemented, including: (1) "ray-plane" 10 | // triangulation and (2) "ray-ray" triangulation. In the former, each optical ray from the 11 | // camera is intersected with the corresponding projector column and/or row. In the later, 12 | // the corresponding optical rays from the camera and projector are intersected; in this 13 | // case, the 3D point is assigned as the closest point to the two (generally skewed) rays. 14 | // 15 | // Details: 16 | // Please read the SIGGRAPH 2009 course notes for additional details. 17 | // 18 | // Douglas Lanman and Gabriel Taubin 19 | // "Build Your Own 3D Scanner: 3D Photography for Beginners" 20 | // ACM SIGGRAPH 2009 Course Notes 21 | // 22 | // Author: 23 | // Douglas Lanman 24 | // Brown University 25 | // July 2009 26 | 27 | // Run the background capture (used to eliminate background points from reconstructions). 28 | int runBackgroundCapture(CvCapture* capture, struct slParams* sl_params, struct slCalib* sl_calib); 29 | 30 | // Run the structured light scanner. 31 | int runStructuredLight(/*CvCapture* capture,*/ struct slParams* sl_params/*, struct slCalib* sl_calib, int scan_index*/); -------------------------------------------------------------------------------- /testScan/testScan.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 头文件 20 | 21 | 22 | 头文件 23 | 24 | 25 | 头文件 26 | 27 | 28 | 头文件 29 | 30 | 31 | 头文件 32 | 33 | 34 | 头文件 35 | 36 | 37 | 38 | 39 | 源文件 40 | 41 | 42 | 源文件 43 | 44 | 45 | 源文件 46 | 47 | 48 | 源文件 49 | 50 | 51 | 源文件 52 | 53 | 54 | 源文件 55 | 56 | 57 | -------------------------------------------------------------------------------- /testScan/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | "./output" 5 | "test" 6 | 0 7 | 8 | 2592 9 | 1944 10 | 1 11 | 12 | 1024 13 | 768 14 | 0 15 | 16 | 26 17 | 22 18 | 19 | 1 20 | 0 21 | 1 22 | 0 23 | 24 | 8 25 | 6 26 | 30. 27 | 30. 28 | 29 | 8 30 | 6 31 | 75 32 | 75 33 | 34 | 2 35 | 1 36 | 1 37 | 200 38 | 50 39 | 250. 40 | 750. 41 | 100. 42 | 20. 43 | 44 | 1 45 | 640 46 | 47 | -------------------------------------------------------------------------------- /testScan/cvUtilProCam.h: -------------------------------------------------------------------------------- 1 | // cvUtilProCam.h: Header file defining auxiliary functions for structured lighting. 2 | // 3 | // Overview: 4 | // This file defines auxiliary functions for implementing structured lighting. Functions 5 | // include basic operations, such as the base-2 logarithm, as well as geometric algorithms, 6 | // including fitting planes to 3D points and intersecting lines with other lines and planes. 7 | // 8 | // Details: 9 | // Please read the SIGGRAPH 2009 course notes for additional details. 10 | // 11 | // Douglas Lanman and Gabriel Taubin 12 | // "Build Your Own 3D Scanner: 3D Photography for Beginners" 13 | // ACM SIGGRAPH 2009 Course Notes 14 | // 15 | // Author: 16 | // Douglas Lanman 17 | // Brown University 18 | // July 2009 19 | 20 | // Calculate the base 2 logarithm. 21 | double log2(double x); 22 | 23 | // Fit a hyperplane to a set of ND points. 24 | void cvFitPlane(const CvMat* points, float* plane); 25 | 26 | // Find intersection between a 3D plane and a 3D line. 27 | void intersectLineWithPlane3D(const float* q, const float* v, const float* w, float* p, float& depth); 28 | 29 | // Find closest point to two 3D lines. 30 | void intersectLineWithLine3D(const float* q1, const float* v1, const float* q2, const float* v2, float* p); 31 | 32 | // Define camera capture (support Logitech QuickCam 9000 raw-mode). 33 | IplImage* cvQueryFrame2(CvCapture* capture, struct slParams* sl_params, bool return_raw = false); 34 | 35 | // Define "safe" camera capture. 36 | // Note: This function will capture a single snapshot after a given instant. 37 | IplImage* cvQueryFrameSafe(CvCapture* capture, struct slParams* sl_params, bool return_raw = false); 38 | 39 | // Capture live image stream (e.g., for adjusting object placement). 40 | int camPreview(/*CvCapture* capture, */struct slParams* sl_params/*, struct slCalib* sl_calib*/); 41 | 42 | // Shade a grayscale image using the "winter" colormap (similar to Matlab's). 43 | void colorizeWinter(IplImage* src, IplImage*& dst, IplImage* mask); 44 | 45 | // Show an image, resampled to desired size. 46 | void cvShowImageResampled(char* name, IplImage* image, int width, int height); 47 | 48 | // Save a VRML-formatted point cloud. 49 | int savePointsVRML(char* filename, CvMat* points, CvMat* normals, CvMat* colors, CvMat* mask); 50 | 51 | // Save XML-formatted configuration file. 52 | void writeConfiguration(const char* filename, struct slParams* sl_params); 53 | 54 | // Read XML-formatted configuration file. 55 | void readConfiguration(const char* filename, struct slParams* sl_params); 56 | 57 | // In-place conversion of a 10-bit raw image to an 8-bit BGR image. 58 | // Note: Only works with Logitech QuickCam 9000 in 10-bit raw-mode (with a Bayer BGGR mosaic). 59 | void cvCvtLogitech9000Raw(IplImage* image, bool return_raw); -------------------------------------------------------------------------------- /testScan/cvCalibrateProCam.h: -------------------------------------------------------------------------------- 1 | // cvCalibrateProCam.h: Header file for projector-camera calibration. 2 | // 3 | // Overview: 4 | // This file defines the functions for projector-camera calibration. Camera calibration is 5 | // implemented using basic OpenCV functions for chessboard detection and homography-based 6 | // calibration, following the method of Zhang [ICCV 2009]. Projector calibration is performed 7 | // using a two-image sequence. First, a physical (i.e., printed) chessboard pattern is 8 | // automatically detected. Afterwards, a virtual chessboard is projected. The first image is 9 | // subtracted from the second. Once again, the built-in OpenCV functions for chessboard 10 | // detection are used to find the virtual chessboard corners. A prior camera calibration 11 | // allows 3D coordinates of each virtual chessboard corner to be reconstructed. Finally, the 12 | // complete set of 2D-to-3D correspondences, mapping 2D projector pixels to 3D points on the 13 | // calibration plane, is used to evaluate the intrinsic projector calibration. A single 14 | // image pair, comprising a static printed chessboard with a projected virtual chessboard 15 | // visible on its surface, is used to estimate the projector-camera extrinsic calibration. 16 | // 17 | // Details: 18 | // Please read the SIGGRAPH 2009 course notes for additional details. 19 | // 20 | // Douglas Lanman and Gabriel Taubin 21 | // "Build Your Own 3D Scanner: 3D Photography for Beginners" 22 | // ACM SIGGRAPH 2009 Course Notes 23 | // 24 | // Author: 25 | // Douglas Lanman 26 | // Brown University 27 | // July 2009 28 | 29 | // Display the camera calibration results to the console. 30 | void displayCamCalib(struct slCalib* sl_calib); 31 | 32 | // Display the projector calibration results to the console. 33 | void displayProjCalib(struct slCalib* sl_calib); 34 | 35 | // Generate a chessboard pattern for projector calibration. 36 | int generateChessboard(struct slParams* sl_params, IplImage*& board, int& border_cols, int& border_rows); 37 | 38 | // Detect chessboard corners (with subpixel refinement). 39 | // Note: Returns 1 if chessboard is found, 0 otherwise. 40 | int detectChessboard(IplImage* frame, CvSize board_size, CvPoint2D32f* corners, int* corner_count CV_DEFAULT(NULL)); 41 | 42 | // Run camera calibration. 43 | int runCameraCalibration(struct slParams* sl_params, struct slCalib* sl_calib); 44 | 45 | // Run projector-camera calibration (including intrinsic and extrinsic parameters). 46 | int runProjectorCalibration(struct slParams* sl_params, struct slCalib* sl_calib, bool calibrate_both); 47 | 48 | // Run projector-camera extrinsic calibration. 49 | int runProCamExtrinsicCalibration(struct slParams* sl_params, struct slCalib* sl_calib); 50 | 51 | // Evaluate geometry of projector-camera optical rays and planes. 52 | int evaluateProCamGeometry(struct slParams* sl_params, struct slCalib* sl_calib); -------------------------------------------------------------------------------- /testScan/testScan.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {10822151-18C9-4ED4-AE56-C9C79C5DB9D4} 31 | Win32Proj 32 | testScan 33 | 34 | 35 | 36 | Application 37 | true 38 | v120 39 | Unicode 40 | 41 | 42 | Application 43 | false 44 | v120 45 | true 46 | Unicode 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | true 60 | D:\StaticSoftware\opencv248\build\x86\vc11\bin;$(ExecutablePath) 61 | D:\StaticSoftware\opencv248\build\include;$(IncludePath) 62 | D:\StaticSoftware\opencv248\build\x86\vc11\lib;$(LibraryPath) 63 | 64 | 65 | false 66 | 67 | 68 | 69 | 70 | 71 | Level3 72 | Disabled 73 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 74 | 4996 75 | 76 | 77 | Console 78 | true 79 | opencv_calib3d248d.lib;opencv_contrib248d.lib;opencv_core248d.lib;opencv_features2d248d.lib;opencv_flann248d.lib;opencv_gpu248d.lib;opencv_highgui248d.lib;opencv_imgproc248d.lib;opencv_legacy248d.lib;opencv_ml248d.lib;opencv_nonfree248d.lib;opencv_objdetect248d.lib;opencv_ocl248d.lib;opencv_photo248d.lib;opencv_stitching248d.lib;opencv_superres248d.lib;opencv_ts248d.lib;opencv_video248d.lib;opencv_videostab248d.lib;%(AdditionalDependencies) 80 | 81 | 82 | 83 | 84 | Level3 85 | 86 | 87 | MaxSpeed 88 | true 89 | true 90 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | 92 | 93 | Console 94 | true 95 | true 96 | true 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /testScan/cvStructuredLight.h: -------------------------------------------------------------------------------- 1 | // cvStructuredLighting.h: Header file for the console application. 2 | // 3 | // Overview: 4 | // This file defines the structures used to store system parameters and calibration details. 5 | // A user-supplied XML-formatted file is used to define system parameters for the console 6 | // application. System calibration parameters can be loaded from prior instances. 7 | // 8 | // Details: 9 | // Please read the SIGGRAPH 2009 course notes for additional details. 10 | // 11 | // Douglas Lanman and Gabriel Taubin 12 | // "Build Your Own 3D Scanner: 3D Photography for Beginners" 13 | // ACM SIGGRAPH 2009 Course Notes 14 | // 15 | // Author: 16 | // Douglas Lanman 17 | // Brown University 18 | // July 2009 19 | 20 | // Define structure for storing structured lighting parameters. 21 | struct slParams{ 22 | 23 | // Output options. 24 | char outdir[1024]; // base output directory 25 | char object[1024]; // object name 26 | bool save; // enable/disable saving of image sequence 27 | 28 | // Camera options. 29 | int cam_w; // camera columns 30 | int cam_h; // camera rows 31 | bool Logitech_9000; // enable/disable Logitech QuickCam 9000 raw-mode (should be disabled for all other cameras) 32 | 33 | // Projector options. 34 | int proj_w; // projector columns 35 | int proj_h; // projector rows 36 | bool proj_invert; // enable/disable inverted projector mode (i.e., camera and projector are flipped with respect to each other) 37 | 38 | // Projector-camera gain parameters. 39 | int cam_gain; // scale factor for camera images 40 | int proj_gain; // scale factor for projector images 41 | 42 | // Calibration model options. 43 | bool cam_dist_model[2]; // enable/disable [tangential, 6th-order radial] distortion components for camera 44 | bool proj_dist_model[2]; // enable/disable [tangential, 6th-order radial] distortion components for projector 45 | 46 | // Define camera calibration chessboard parameters. 47 | // Note: Width/height are number of "interior" corners, excluding outside edges. 48 | int cam_board_w; // interior chessboard corners (along width) 49 | int cam_board_h; // interior chessboard corners (along height) 50 | float cam_board_w_mm; // physical length of chessboard square (width in mm) 51 | float cam_board_h_mm; // physical length of chessboard square (height in mm) 52 | 53 | // Define projector calibration chessboard parameters. 54 | // Note: Width/height are number of "interior" corners, excluding outside edges. 55 | int proj_board_w; // interior chessboard corners (along width) 56 | int proj_board_h; // interior chessboard corners (along height) 57 | int proj_board_w_pixels; // physical length of chessboard square (width in pixels) 58 | int proj_board_h_pixels; // physical length of chessboard square (height in pixels) 59 | 60 | // General options. 61 | int mode; // structured light reconstruction mode (1 = "ray-plane", 2 = "ray-ray") 62 | bool scan_cols; // enable/disable column scanning 63 | bool scan_rows; // enable/disable row scanning 64 | int delay; // frame delay between projection and image capture (in ms) 65 | int thresh; // minimum contrast threshold for decoding (maximum of 255) 66 | float dist_range[2]; // {minimum, maximum} distance (from camera), otherwise point is rejected 67 | float dist_reject; // rejection distance (for outlier removal) if row and column scanning are both enabled (in mm) 68 | float background_depth_thresh; // threshold distance for background removal (in mm) 69 | 70 | // Visualization options. 71 | bool display; // enable/disable display of intermediate results (e.g., image sequence, calibration data, etc.) 72 | int window_w; // camera display window width (height is derived) 73 | int window_h; // camera display window width (derived parameter) 74 | }; 75 | 76 | // Define structure for structured lighting calibration parameters. 77 | struct slCalib{ 78 | 79 | // Camera calibration. 80 | CvMat* cam_intrinsic; // camera intrinsic parameter matrix 81 | CvMat* cam_distortion; // camera distortion coefficient vector 82 | CvMat* cam_extrinsic; // camera extrinsic parameter matrix 83 | 84 | // Projector calibration. 85 | CvMat* proj_intrinsic; // projector intrinsic parameter matrix 86 | CvMat* proj_distortion; // projector distortion coefficient vector 87 | CvMat* proj_extrinsic; // projector extrinsic parameter matrix 88 | 89 | // Projector-camera geometric parameters. 90 | // Note: All quantities defined in the camera coordinate system. 91 | CvMat* cam_center; // camera center of projection 92 | CvMat* proj_center; // projector center of projection 93 | CvMat* cam_rays; // optical rays for each camera pixel 94 | CvMat* proj_rays; // optical rays for each projector pixel 95 | CvMat* proj_column_planes; // plane equations describing every projector column 96 | CvMat* proj_row_planes; // plane equations describing every projector row 97 | 98 | // Flags to indicate calibration status. 99 | bool cam_intrinsic_calib; // flag to indicate state of intrinsic camera calibration 100 | bool proj_intrinsic_calib; // flag to indicate state of intrinsic projector calibration 101 | bool procam_extrinsic_calib; // flag to indicate state of extrinsic projector-camera calibration 102 | 103 | // Background model (used to segment foreground objects of interest from static background). 104 | CvMat* background_depth_map; // background depth map 105 | IplImage* background_image; // background image 106 | IplImage* background_mask; // background mask 107 | }; -------------------------------------------------------------------------------- /testScan/cvUtilProCam.cpp: -------------------------------------------------------------------------------- 1 | // cvUtilProCam.h: Implementations of auxiliary functions for structured lighting. 2 | // 3 | // Overview: 4 | // This file defines auxiliary functions for implementing structured lighting. Functions 5 | // include basic operations, such as the base-2 logarithm, as well as geometric algorithms, 6 | // including fitting planes to 3D points and intersecting lines with other lines and planes. 7 | // 8 | // Details: 9 | // Please read the SIGGRAPH 2009 course notes for additional details. 10 | // 11 | // Douglas Lanman and Gabriel Taubin 12 | // "Build Your Own 3D Scanner: 3D Photography for Beginners" 13 | // ACM SIGGRAPH 2009 Course Notes 14 | // 15 | // Author: 16 | // Douglas Lanman 17 | // Brown University 18 | // July 2009 19 | 20 | #include "stdafx.h" 21 | #include "cvStructuredLight.h" 22 | #include "cvUtilProCam.h" 23 | 24 | // Calculate the base 2 logarithm. 25 | double log2(double x) 26 | { 27 | return log(x)/log(2.0); 28 | } 29 | 30 | // Fit a hyperplane to a set of ND points. 31 | // Note: Input points must be in the form of an NxM matrix, where M is the dimensionality. 32 | // This function finds the best-fit plane P, in the least-squares 33 | // sense, between the points (X,Y,Z). The resulting plane P is described 34 | // by the coefficient vector W, where W(1)*X + W(2)*Y +W(3)*Z = W(3), for 35 | // (X,Y,Z) on the plane P. 36 | void cvFitPlane(const CvMat* points, float* plane){ 37 | 38 | // Estimate geometric centroid. 39 | int nrows = points->rows; 40 | int ncols = points->cols; 41 | int type = points->type; 42 | CvMat* centroid = cvCreateMat(1, ncols, type); 43 | cvSet(centroid, cvScalar(0)); 44 | for(int c=0; cdata.fl[c] += points->data.fl[ncols*r+c]; 47 | centroid->data.fl[c] /= nrows; 48 | } 49 | 50 | // Subtract geometric centroid from each point. 51 | CvMat* points2 = cvCreateMat(nrows, ncols, type); 52 | for(int r=0; rdata.fl[ncols*r+c] = points->data.fl[ncols*r+c] - centroid->data.fl[c]; 55 | 56 | // Evaluate SVD of covariance matrix. 57 | CvMat* A = cvCreateMat(ncols, ncols, type); 58 | CvMat* W = cvCreateMat(ncols, ncols, type); 59 | CvMat* V = cvCreateMat(ncols, ncols, type); 60 | cvGEMM(points2, points, 1, NULL, 0, A, CV_GEMM_A_T); 61 | cvSVD(A, W, NULL, V, CV_SVD_V_T); 62 | 63 | // Assign plane coefficients by singular vector corresponding to smallest singular value. 64 | plane[ncols] = 0; 65 | for(int c=0; cdata.fl[ncols*(ncols-1)+c]; 67 | plane[ncols] += plane[c]*centroid->data.fl[c]; 68 | } 69 | 70 | // Release allocated resources. 71 | cvReleaseMat(¢roid); 72 | cvReleaseMat(&points2); 73 | cvReleaseMat(&A); 74 | cvReleaseMat(&W); 75 | cvReleaseMat(&V); 76 | } 77 | 78 | // Find intersection between a 3D plane and a 3D line. 79 | // Note: Finds the point of intersection of a line in parametric form 80 | // (i.e., containing a point Q and spanned by the vector V, with 81 | // a plane W defined in implicit form. Note, this function does 82 | // not handle certain "degenerate" cases, since they do not occur 83 | // in practice with the structured lighting configuration. 84 | void intersectLineWithPlane3D(const float* q, 85 | const float* v, 86 | const float* w, 87 | float* p, 88 | float& depth){ 89 | 90 | // Evaluate inner products. 91 | float n_dot_q = 0, n_dot_v = 0; 92 | for(int i=0; i<3; i++){ 93 | n_dot_q += w[i]*q[i]; 94 | n_dot_v += w[i]*v[i]; 95 | } 96 | 97 | // Evaluate point of intersection P. 98 | depth = (w[3]-n_dot_q)/n_dot_v; 99 | for(int i=0; i<3; i++) 100 | p[i] = q[i] + depth*v[i]; 101 | } 102 | 103 | // Find closest point to two 3D lines. 104 | // Note: Finds the closest 3D point between two 3D lines defined in parametric 105 | /// form (i.e., containing a point Q and spanned by the vector V). Note, 106 | // this function does not handle certain "degenerate" cases, since they 107 | // do not occur in practice with the structured lighting configuration. 108 | void intersectLineWithLine3D(const float* q1, 109 | const float* v1, 110 | const float* q2, 111 | const float* v2, 112 | float* p){ 113 | 114 | // Define intermediate quantities. 115 | float q12[3], v1_dot_v1 = 0, v2_dot_v2 = 0, v1_dot_v2 = 0, q12_dot_v1 = 0, q12_dot_v2 = 0; 116 | for(int i=0; i<3; i++){ 117 | q12[i] = q1[i]-q2[i]; 118 | v1_dot_v1 += v1[i]*v1[i]; 119 | v2_dot_v2 += v2[i]*v2[i]; 120 | v1_dot_v2 += v1[i]*v2[i]; 121 | q12_dot_v1 += q12[i]*v1[i]; 122 | q12_dot_v2 += q12[i]*v2[i]; 123 | } 124 | 125 | // Calculate scale factors. 126 | float s, t, denom; 127 | denom = v1_dot_v1*v2_dot_v2 - v1_dot_v2*v1_dot_v2; 128 | s = (v1_dot_v2/denom)*q12_dot_v2 - (v2_dot_v2/denom)*q12_dot_v1; 129 | t = -(v1_dot_v2/denom)*q12_dot_v1 + (v1_dot_v1/denom)*q12_dot_v2; 130 | 131 | // Evaluate closest point. 132 | for(int i=0; i<3; i++) 133 | p[i] = ( (q1[i]+s*v1[i]) + (q2[i]+t*v2[i]) )/2; 134 | } 135 | 136 | // Define camera capture (support Logitech QuickCam 9000 raw-mode). 137 | IplImage* cvQueryFrame2(CvCapture* capture, struct slParams* sl_params, bool return_raw){ 138 | IplImage* cam_frame = cvQueryFrame(capture); 139 | if(sl_params->Logitech_9000) 140 | cvCvtLogitech9000Raw(cam_frame, return_raw); 141 | return cam_frame; 142 | } 143 | 144 | 145 | // Define "safe" camera capture. 146 | // Note: This function will capture a single snapshot after a given instant. 147 | IplImage* cvQueryFrameSafe(CvCapture* capture, struct slParams* sl_params, bool return_raw){ 148 | cvQueryFrame2(capture, sl_params, return_raw); 149 | return cvQueryFrame2(capture, sl_params, return_raw); 150 | } 151 | 152 | // Capture live image stream (e.g., for adjusting object placement). 153 | int camPreview(/*CvCapture* capture, */struct slParams* sl_params/*, struct slCalib* sl_calib*/){ 154 | 155 | // Create a window to display captured frames. 156 | IplImage* cam_frame = NULL/*cvQueryFrame2(capture, sl_params)*/; 157 | QueryFrameMX500(&cam_frame); 158 | IplImage* proj_frame = cvCreateImage(cvSize(sl_params->proj_w, sl_params->proj_h), IPL_DEPTH_8U, 1); 159 | cvNamedWindow("camWindow", CV_WINDOW_AUTOSIZE); 160 | cvCreateTrackbar("Cam. Gain", "camWindow", &sl_params->cam_gain, 100, NULL); 161 | cvCreateTrackbar("Proj. Gain", "camWindow", &sl_params->proj_gain, 100, NULL); 162 | HWND camWindow = (HWND)cvGetWindowHandle("camWindow"); 163 | BringWindowToTop(camWindow); 164 | cvWaitKey(1); 165 | 166 | // Capture live image stream. 167 | int cvKey = -1, cvKey_temp = -1; 168 | while(1){ 169 | 170 | // Project white image. 171 | cvSet(proj_frame, cvScalar(255)); 172 | cvScale(proj_frame, proj_frame, 2.*(sl_params->proj_gain/100.), 0); 173 | cvShowImage("projWindow", proj_frame); 174 | cvKey_temp = cvWaitKey(1); 175 | if(cvKey_temp != -1) 176 | cvKey = cvKey_temp; 177 | 178 | // Capture next frame and update display window. 179 | //cam_frame = cvQueryFrame2(capture, sl_params); 180 | QueryFrameMX500(&cam_frame); 181 | cvScale(cam_frame, cam_frame, 2.*(sl_params->cam_gain/100.), 0); 182 | cvShowImageResampled("camWindow", cam_frame, sl_params->window_w, sl_params->window_h); 183 | cvKey_temp = cvWaitKey(10); 184 | if(cvKey_temp != -1) 185 | cvKey = cvKey_temp; 186 | 187 | // Exit on user interaction. 188 | if(cvKey != -1) 189 | break; 190 | } 191 | 192 | // Project black image. 193 | cvZero(proj_frame); 194 | cvShowImage("projWindow", proj_frame); 195 | cvKey_temp = cvWaitKey(1); 196 | 197 | // Return without errors. 198 | cvDestroyWindow("camWindow"); 199 | cvReleaseImage(&proj_frame); 200 | return 0; 201 | } 202 | 203 | // Shade a grayscale image using the "winter" colormap (similar to Matlab's). 204 | void colorizeWinter(IplImage* src, IplImage*& dst, IplImage* mask){ 205 | 206 | // Create an increasing linear-ramp in the green channel. 207 | cvMerge(NULL, src, NULL, NULL, dst); 208 | 209 | // Create a decreasing linear-ramp in the blue channel. 210 | IplImage* blue = cvCloneImage(src); 211 | cvSubRS(src, cvScalar(255.0), blue, mask); 212 | cvMerge(blue, NULL, NULL, NULL, dst); 213 | 214 | // Release allocated resources. 215 | cvReleaseImage(&blue); 216 | } 217 | 218 | // Show an image, resampled to desired size. 219 | void cvShowImageResampled(char* name, 220 | IplImage* image, 221 | int width, 222 | int height){ 223 | 224 | // Allocate resampled image. 225 | IplImage* resampled_image = 226 | cvCreateImage(cvSize(width, height), image->depth, image->nChannels); 227 | 228 | // Resize image. 229 | cvResize(image, resampled_image, CV_INTER_LINEAR); 230 | 231 | // Display resampled image. 232 | cvShowImage(name, resampled_image); 233 | 234 | // Release allocated resources. 235 | cvReleaseImage(&resampled_image); 236 | } 237 | 238 | // Save a VRML-formatted point cloud. 239 | int savePointsVRML(char* filename, 240 | CvMat* points, 241 | CvMat* normals, 242 | CvMat* colors, 243 | CvMat* mask){ 244 | 245 | // Open output file and create header. 246 | FILE* pFile = fopen(filename, "w"); 247 | if(pFile == NULL){ 248 | fprintf(stderr,"ERROR: Cannot open VRML file!\n"); 249 | return -1; 250 | } 251 | fprintf(pFile, "#VRML V2.0 utf8\n"); 252 | fprintf(pFile, "Shape {\n"); 253 | fprintf(pFile, " geometry IndexedFaceSet {\n"); 254 | 255 | // Output points (i.e., indexed face set vertices). 256 | // Note: Flip y-component for compatibility with Java-based viewer. 257 | if(points != NULL){ 258 | fprintf(pFile, " coord Coordinate {\n"); 259 | fprintf(pFile, " point [\n"); 260 | for(int c=0; ccols; c++){ 261 | if(mask == NULL || mask->data.fl[c] != 0){ 262 | for(int r=0; rrows; r++){ 263 | if(r != 1) 264 | fprintf(pFile, " %f ", points->data.fl[c + points->cols*r]); 265 | else 266 | fprintf(pFile, " %f ", -points->data.fl[c + points->cols*r]); 267 | } 268 | fprintf(pFile, "\n"); 269 | } 270 | } 271 | fprintf(pFile, " ]\n"); 272 | fprintf(pFile, " }\n"); 273 | } 274 | 275 | // Output normals (if provided). 276 | // Note: Flips normals, for compatibility with Java-based viewer. 277 | if(normals != NULL){ 278 | fprintf(pFile, " normalPerVertex TRUE\n"); 279 | fprintf(pFile, " normal Normal {\n"); 280 | fprintf(pFile, " vector [\n"); 281 | for(int c=0; ccols; c++){ 282 | if(mask == NULL || mask->data.fl[c] != 0){ 283 | for(int r=0; rrows; r++) 284 | fprintf(pFile, " %f ", -normals->data.fl[c + normals->cols*r]); 285 | fprintf(pFile, "\n"); 286 | } 287 | } 288 | fprintf(pFile, " ]\n"); 289 | fprintf(pFile, " }\n"); 290 | } 291 | 292 | // Output colors (if provided). 293 | // Note: Assumes input is an 8-bit RGB color array. 294 | if(colors != NULL){ 295 | fprintf(pFile, " colorPerVertex TRUE\n"); 296 | fprintf(pFile, " color Color {\n"); 297 | fprintf(pFile, " color [\n"); 298 | for(int c=0; ccols; c++){ 299 | if(mask == NULL || mask->data.fl[c] != 0){ 300 | for(int r=0; rrows; r++) 301 | fprintf(pFile, " %f ", colors->data.fl[c + colors->cols*r]); 302 | fprintf(pFile, "\n"); 303 | } 304 | } 305 | fprintf(pFile, " ]\n"); 306 | fprintf(pFile, " }\n"); 307 | } 308 | 309 | // Create footer and close file. 310 | fprintf(pFile, " }\n"); 311 | fprintf(pFile, "}\n"); 312 | if(fclose(pFile) != 0){ 313 | printf("ERROR: Cannot close VRML file!\n"); 314 | return -1; 315 | } 316 | 317 | // Return without errors. 318 | return 0; 319 | } 320 | 321 | // Save XML-formatted configuration file. 322 | void writeConfiguration(const char* filename, struct slParams* sl_params){ 323 | 324 | // Create file storage for XML-formatted configuration file. 325 | CvFileStorage* fs = cvOpenFileStorage(filename, 0, CV_STORAGE_WRITE); 326 | 327 | // Write output directory and object (or sequence) name. 328 | cvStartWriteStruct(fs, "output", CV_NODE_MAP); 329 | cvWriteString(fs, "output_directory", sl_params->outdir, 1); 330 | cvWriteString(fs, "object_name", sl_params->object, 1); 331 | cvWriteInt(fs, "save_intermediate_results", sl_params->save); 332 | cvEndWriteStruct(fs); 333 | 334 | // Write camera parameters. 335 | cvStartWriteStruct(fs, "camera", CV_NODE_MAP); 336 | cvWriteInt(fs, "width", sl_params->cam_w); 337 | cvWriteInt(fs, "height", sl_params->cam_h); 338 | cvWriteInt(fs, "Logitech_Quickcam_9000_raw_mode", sl_params->Logitech_9000); 339 | cvEndWriteStruct(fs); 340 | 341 | // Write projector parameters. 342 | cvStartWriteStruct(fs, "projector", CV_NODE_MAP); 343 | cvWriteInt(fs, "width", sl_params->proj_w); 344 | cvWriteInt(fs, "height", sl_params->proj_h); 345 | cvWriteInt(fs, "invert_projector", sl_params->proj_invert); 346 | cvEndWriteStruct(fs); 347 | 348 | // Write camera and projector gain parameters. 349 | cvStartWriteStruct(fs, "gain", CV_NODE_MAP); 350 | cvWriteInt(fs, "camera_gain", sl_params->cam_gain); 351 | cvWriteInt(fs, "projector_gain", sl_params->proj_gain); 352 | cvEndWriteStruct(fs); 353 | 354 | // Write distortion model parameters. 355 | cvStartWriteStruct(fs, "distortion_model", CV_NODE_MAP); 356 | cvWriteInt(fs, "enable_tangential_camera", sl_params->cam_dist_model[0]); 357 | cvWriteInt(fs, "enable_6th_order_radial_camera", sl_params->cam_dist_model[1]); 358 | cvWriteInt(fs, "enable_tangential_projector", sl_params->proj_dist_model[0]); 359 | cvWriteInt(fs, "enable_6th_order_radial_projector", sl_params->proj_dist_model[1]); 360 | cvEndWriteStruct(fs); 361 | 362 | // Write camera calibration chessboard parameters. 363 | cvStartWriteStruct(fs, "camera_chessboard", CV_NODE_MAP); 364 | cvWriteInt(fs, "interior_horizontal_corners", sl_params->cam_board_w); 365 | cvWriteInt(fs, "interior_vertical_corners", sl_params->cam_board_h); 366 | cvWriteReal(fs, "square_width_mm", sl_params->cam_board_w_mm); 367 | cvWriteReal(fs, "square_height_mm", sl_params->cam_board_h_mm); 368 | cvEndWriteStruct(fs); 369 | 370 | // Write projector calibration chessboard parameters. 371 | cvStartWriteStruct(fs, "projector_chessboard", CV_NODE_MAP); 372 | cvWriteInt(fs, "interior_horizontal_corners", sl_params->proj_board_w); 373 | cvWriteInt(fs, "interior_vertical_corners", sl_params->proj_board_h); 374 | cvWriteInt(fs, "square_width_pixels", sl_params->proj_board_w_pixels); 375 | cvWriteInt(fs, "square_height_pixels", sl_params->proj_board_h_pixels); 376 | cvEndWriteStruct(fs); 377 | 378 | // Write scanning and reconstruction parameters. 379 | cvStartWriteStruct(fs, "scanning_and_reconstruction", CV_NODE_MAP); 380 | cvWriteInt(fs, "mode", sl_params->mode); 381 | cvWriteInt(fs, "reconstruct_columns", sl_params->scan_cols); 382 | cvWriteInt(fs, "reconstruct_rows", sl_params->scan_rows); 383 | cvWriteInt(fs, "frame_delay_ms", sl_params->delay); 384 | cvWriteInt(fs, "minimum_contrast_threshold", sl_params->thresh); 385 | cvWriteReal(fs, "minimum_distance_mm", sl_params->dist_range[0]); 386 | cvWriteReal(fs, "maximum_distance_mm", sl_params->dist_range[1]); 387 | cvWriteReal(fs, "maximum_distance_variation_mm", sl_params->dist_reject); 388 | cvWriteReal(fs, "minimum_background_distance_mm", sl_params->background_depth_thresh); 389 | cvEndWriteStruct(fs); 390 | 391 | // Write visualization options. 392 | cvStartWriteStruct(fs, "visualization", CV_NODE_MAP); 393 | cvWriteInt(fs, "display_intermediate_results", sl_params->display); 394 | cvWriteInt(fs, "display_window_width_pixels", sl_params->window_w); 395 | cvEndWriteStruct(fs); 396 | 397 | // Close file storage for XML-formatted configuration file. 398 | cvReleaseFileStorage(&fs); 399 | } 400 | 401 | // Read XML-formatted configuration file. 402 | void readConfiguration(const char* filename, struct slParams* sl_params){ 403 | 404 | // Open file storage for XML-formatted configuration file. 405 | CvFileStorage* fs = cvOpenFileStorage(filename, 0, CV_STORAGE_READ); 406 | 407 | // Read output directory and object (or sequence) name. 408 | CvFileNode* m = cvGetFileNodeByName(fs, 0, "output"); 409 | strcpy(sl_params->outdir, cvReadStringByName(fs, m, "output_directory", "./output")); 410 | strcpy(sl_params->object, cvReadStringByName(fs, m, "object_name", "./output")); 411 | sl_params->save = (cvReadIntByName(fs, m, "save_intermediate_results", 0) != 0); 412 | 413 | // Read camera parameters. 414 | m = cvGetFileNodeByName(fs, 0, "camera"); 415 | sl_params->cam_w = cvReadIntByName(fs, m, "width", 960); 416 | sl_params->cam_h = cvReadIntByName(fs, m, "height", 720); 417 | sl_params->Logitech_9000 = (cvReadIntByName(fs, m, "Logitech_Quickcam_9000_raw_mode", 0) != 0); 418 | 419 | // Read projector parameters. 420 | m = cvGetFileNodeByName(fs, 0, "projector"); 421 | sl_params->proj_w = cvReadIntByName(fs, m, "width", 1024); 422 | sl_params->proj_h = cvReadIntByName(fs, m, "height", 768); 423 | sl_params->proj_invert = (cvReadIntByName(fs, m, "invert_projector", 0) != 0); 424 | 425 | // Read camera and projector gain parameters. 426 | m = cvGetFileNodeByName(fs, 0, "gain"); 427 | sl_params->cam_gain = cvReadIntByName(fs, m, "camera_gain", 50); 428 | sl_params->proj_gain = cvReadIntByName(fs, m, "projector_gain", 50); 429 | 430 | // Read distortion model parameters. 431 | m = cvGetFileNodeByName(fs, 0, "distortion_model"); 432 | sl_params->cam_dist_model[0] = (cvReadIntByName(fs, m, "enable_tangential_camera", 0) != 0); 433 | sl_params->cam_dist_model[1] = (cvReadIntByName(fs, m, "enable_6th_order_radial_camera", 0) != 0); 434 | sl_params->proj_dist_model[0] = (cvReadIntByName(fs, m, "enable_tangential_projector", 0) != 0); 435 | sl_params->proj_dist_model[1] = (cvReadIntByName(fs, m, "enable_6th_order_radial_projector", 0) != 0); 436 | 437 | // Read camera calibration chessboard parameters. 438 | m = cvGetFileNodeByName(fs, 0, "camera_chessboard"); 439 | sl_params->cam_board_w = cvReadIntByName(fs, m, "interior_horizontal_corners", 8); 440 | sl_params->cam_board_h = cvReadIntByName(fs, m, "interior_vertical_corners", 6); 441 | sl_params->cam_board_w_mm = (float)cvReadRealByName(fs, m, "square_width_mm", 30.0); 442 | sl_params->cam_board_h_mm = (float)cvReadRealByName(fs, m, "square_height_mm", 30.0); 443 | 444 | // Read projector calibration chessboard parameters. 445 | m = cvGetFileNodeByName(fs, 0, "projector_chessboard"); 446 | sl_params->proj_board_w = cvReadIntByName(fs, m, "interior_horizontal_corners", 8); 447 | sl_params->proj_board_h = cvReadIntByName(fs, m, "interior_vertical_corners", 6); 448 | sl_params->proj_board_w_pixels = cvReadIntByName(fs, m, "square_width_pixels", 75); 449 | sl_params->proj_board_h_pixels = cvReadIntByName(fs, m, "square_height_pixels", 75); 450 | 451 | // Read scanning and reconstruction parameters. 452 | m = cvGetFileNodeByName(fs, 0, "scanning_and_reconstruction"); 453 | sl_params->mode = cvReadIntByName(fs, m, "mode", 2); 454 | sl_params->scan_cols = (cvReadIntByName(fs, m, "reconstruct_columns", 1) != 0); 455 | sl_params->scan_rows = (cvReadIntByName(fs, m, "reconstruct_rows", 1) != 0); 456 | sl_params->delay = cvReadIntByName(fs, m, "frame_delay_ms", 200); 457 | sl_params->thresh = cvReadIntByName(fs, m, "minimum_contrast_threshold", 32); 458 | sl_params->dist_range[0] = (float) cvReadRealByName(fs, m, "minimum_distance_mm", 0.0); 459 | sl_params->dist_range[1] = (float) cvReadRealByName(fs, m, "maximum_distance_mm", 1.0e4); 460 | sl_params->dist_reject = (float) cvReadRealByName(fs, m, "maximum_distance_variation_mm", 10.0); 461 | sl_params->background_depth_thresh = (float) cvReadRealByName(fs, m, "minimum_background_distance_mm", 20.0); 462 | 463 | // Read visualization options. 464 | m = cvGetFileNodeByName(fs, 0, "visualization"); 465 | sl_params->display = (cvReadIntByName(fs, m, "display_intermediate_results", 1) != 0); 466 | sl_params->window_w = cvReadIntByName(fs, m, "display_window_width_pixels", 640); 467 | 468 | // Enable both row and column scanning, if "ray-ray" reconstruction mode is enabled. 469 | if(sl_params->mode == 2){ 470 | sl_params->scan_cols = true; 471 | sl_params->scan_rows = true; 472 | } 473 | 474 | // Set camera visualization window dimensions. 475 | sl_params->window_h = (int)ceil((float)sl_params->window_w*((float)sl_params->cam_h/(float)sl_params->cam_w)); 476 | 477 | // Close file storage for XML-formatted configuration file. 478 | cvReleaseFileStorage(&fs); 479 | } 480 | 481 | // In-place conversion of a 10-bit raw image to an 8-bit BGR image. 482 | // Note: Only works with Logitech QuickCam 9000 in 10-bit raw-mode (with a Bayer BGGR mosaic). 483 | // See: http://www.quickcamteam.net/documentation/how-to/how-to-enable-raw-streaming-on-logitech-webcams 484 | void cvCvtLogitech9000Raw(IplImage* image, bool return_raw){ 485 | IplImage* raw_image = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_8U, 1); 486 | for(int r=0; rheight; r++){ 487 | uchar* image_data = (uchar*)(image->imageData + r*image->widthStep); 488 | uchar* raw_image_data = (uchar*)(raw_image->imageData + r*raw_image->widthStep); 489 | for(int c=0; cwidth; c++) 490 | raw_image_data[c] = uchar((255./1023.)*(image_data[3*c] + 256*image_data[3*c+1])); 491 | } 492 | if(return_raw) 493 | cvMerge(raw_image, raw_image, raw_image, NULL, image); 494 | else 495 | cvCvtColor(raw_image, image, CV_BayerBG2BGR); 496 | cvReleaseImage(&raw_image); 497 | } --------------------------------------------------------------------------------