├── README.md ├── camera_models ├── NikonD7000 │ ├── README.txt │ ├── jpg2raw_coefs.txt │ ├── jpg2raw_ctrlPoints.txt │ ├── jpg2raw_destPoints.txt │ ├── jpg2raw_respFcns.txt │ ├── jpg2raw_transform.txt │ ├── jpg2raw_validRange.txt │ ├── raw2jpg_coefs.txt │ ├── raw2jpg_ctrlPoints.txt │ ├── raw2jpg_destPoints.txt │ ├── raw2jpg_respFcns.txt │ ├── raw2jpg_transform.txt │ └── raw2jpg_validRange.txt └── README.txt ├── imgs ├── NikonD7000FL │ ├── DSC_0916.JPG │ ├── DSC_0916.NEF │ ├── DSC_0916.NEF.demos_3C.png │ ├── DSC_0916.NEF.raw_1C.tiff │ └── DSC_0916.png └── README.txt └── src ├── Halide ├── ImgPipeConfig.h ├── ImgPipe_Halide.cpp ├── LoadCamModel.cpp ├── LoadCamModel.h ├── Makefile ├── MatrixOps.cpp ├── MatrixOps.h ├── README.txt └── clock.h ├── Matlab ├── ImgPipe_Matlab.m ├── README.txt └── sample_pipe_results │ ├── README.txt │ ├── backward_images │ ├── DSC_0916.JPG.p1.back_ref.tif │ ├── DSC_0916.JPG.p1.back_ref_colored.tif │ ├── DSC_0916.JPG.p1.back_result.tif │ ├── DSC_0916.JPG.p2.back_ref.tif │ ├── DSC_0916.JPG.p2.back_ref_colored.tif │ ├── DSC_0916.JPG.p2.back_result.tif │ ├── DSC_0916.JPG.p3.back_ref.tif │ ├── DSC_0916.JPG.p3.back_ref_colored.tif │ ├── DSC_0916.JPG.p3.back_result.tif │ ├── DSC_0916.JPG.p4.back_ref.tif │ ├── DSC_0916.JPG.p4.back_ref_colored.tif │ ├── DSC_0916.JPG.p4.back_result.tif │ ├── DSC_0916.JPG.p5.back_ref.tif │ ├── DSC_0916.JPG.p5.back_ref_colored.tif │ ├── DSC_0916.JPG.p5.back_result.tif │ ├── DSC_0916.JPG.p6.back_ref.tif │ ├── DSC_0916.JPG.p6.back_ref_colored.tif │ ├── DSC_0916.JPG.p6.back_result.tif │ ├── DSC_0916.JPG.p7.back_ref.tif │ ├── DSC_0916.JPG.p7.back_ref_colored.tif │ ├── DSC_0916.JPG.p7.back_result.tif │ ├── DSC_0916.JPG.p8.back_ref.tif │ ├── DSC_0916.JPG.p8.back_ref_colored.tif │ └── DSC_0916.JPG.p8.back_result.tif │ ├── backward_results.txt │ ├── forward_images │ ├── DSC_0916.NEF.raw_1C.tiff.p1.forward_reference.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p1.forward_result.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p2.forward_reference.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p2.forward_result.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p3.forward_reference.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p3.forward_result.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p4.forward_reference.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p4.forward_result.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p5.forward_reference.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p5.forward_result.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p6.forward_reference.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p6.forward_result.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p7.forward_reference.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p7.forward_result.tif │ ├── DSC_0916.NEF.raw_1C.tiff.p8.forward_reference.tif │ └── DSC_0916.NEF.raw_1C.tiff.p8.forward_result.tif │ └── forward_results.txt ├── OpenCV └── compare_imgs.py └── scripts ├── ImgPipe.cpp ├── Makefile ├── README.txt └── RawPreproc.cpp /README.md: -------------------------------------------------------------------------------- 1 | # ReversiblePipeline 2 | 3 | This is an implementation of a pre-learned camera image 4 | processing model. A description of the model can be found in 5 | "A New In-Camera Imaging Model for Color Computer Vision 6 | and its Application" by Seon Joo Kim, Hai Ting Lin, Zheng Lu, 7 | Sabine Susstrunk, Stephen Lin, and Michael S. Brown. Code for 8 | learning a new model can be found at the original project 9 | page. This particular implementation was written by 10 | Mark Buckler. 11 | 12 | If you are looking for the full Configurable & Reversible Imaging Pipeline (CRIP) as seen in the paper [Reconfiguring the Imaging Pipeline for Computer Vision](https://arxiv.org/abs/1705.04352) by Mark Buckler, Suren Jayasuriya, and Adrian Sampson, see [this repository](https://github.com/cucapra/approx-vision) instead. 13 | 14 | Original Project Page: 15 | * http://www.comp.nus.edu.sg/~brown/radiometric_calibration/ 16 | 17 | Model Format Readme: 18 | * http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/Model_param/readme.pdf 19 | 20 | 21 | ## Pipeline Implementation Descriptions 22 | 23 | * Strict Forward Pipeline 24 | 25 | A forward only pipeline which displays intermediate as well as final 26 | outputs is provided in the src/scripts directory. Use this if you 27 | want a fast forward pipeline but dont need to emulate a specific 28 | camera model or reverse the processing. This implementation uses 29 | LibRaw and OpenCV. 30 | 31 | * Reversible Matlab Pipeline 32 | 33 | This implementation can be found in src/Matlab. Use this pipeline 34 | if you would like to use one of the available forward and backward 35 | camera pipeline models, aren't concerned about speed, and would 36 | like to take advantage of Matlab's many pre-built image processing 37 | tools. Note that this implementation is prohibitively slow 38 | if you would like to process large images. Its default is to do 39 | patch based processing to enable a reasonable run time. 40 | 41 | * Reversible Halide Pipeline 42 | 43 | This can be found in src/Halide. Use this pipeline if you want to 44 | process full high resolution images with both a backward and 45 | forward image processing pipeline implementation. The model is 46 | fully implemented with Halide Funcs, and some basic scheduling 47 | for loop unrolling and pre-computation is provided. Scheduling for 48 | paralellism on the CPU or GPU can be easily added by the user. 49 | Do note that while this implementation is much faster than Matlab, 50 | it will take close to 10 minutes to process a 5000x3000 pixel image. 51 | 52 | ## General Use Instructions 53 | 54 | Instructions for using all of the different pieces of the pipeline 55 | can be found in readmes like this one within the appropriate 56 | directories. All code has been tested with Ubuntu 14.04, but with 57 | small edits to makefiles all code should work with OS X as well. 58 | 59 | ## Dependencies 60 | 61 | * Development versions of LibRaw and OpenCV (for preprocessing) 62 | * Matlab (for Matlab pipeline) 63 | * Halide (for Halide pipeline) 64 | -------------------------------------------------------------------------------- /camera_models/NikonD7000/README.txt: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # 3 | # Camera Pipeline Model for Nikon D7000 4 | # 5 | ##################################################################### 6 | 7 | 8 | ##################################################################### 9 | # Description 10 | ##################################################################### 11 | 12 | This directory contains model parameters for the Nikon D7000 camera 13 | under indoor lighting conditions and using the Normal camera 14 | picture style. This model was created by Haiting Lin, Michael Brown, 15 | and others. Their methodology can be found in the PAMI paper entitled 16 | "A New In-Camera Imaging Model for Color Computer Vision and its 17 | Application". 18 | 19 | ##################################################################### 20 | # White Balance Setting Codes 21 | ##################################################################### 22 | 23 | Tu - 3 - Tungsten 24 | Fs - 4 - Flash 25 | Su - 9 - Sunny 26 | Cl - 10 - Cloudy 27 | Sh - 11 - Shade 28 | Fl - 14 - Fluorescent 29 | 30 | ##################################################################### 31 | # Useful Links 32 | ##################################################################### 33 | 34 | More models (see Data sets): 35 | http://www.comp.nus.edu.sg/~brown/radiometric_calibration/ 36 | 37 | Readme for model format: 38 | http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/Model_param/readme.pdf 39 | 40 | This model: 41 | http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/Model_param/NikonD7000_Indoor20110507_4s/N.zip 42 | -------------------------------------------------------------------------------- /camera_models/NikonD7000/jpg2raw_respFcns.txt: -------------------------------------------------------------------------------- 1 | 16400.000000 0.000000 0.000000 0.000000 2 | 0.000000 0.000000 0.000000 3 | 0.001304 0.001089 0.001547 4 | 0.002206 0.001898 0.002376 5 | 0.002950 0.002692 0.003020 6 | 0.003533 0.003316 0.003549 7 | 0.004035 0.003859 0.004047 8 | 0.004568 0.004470 0.004677 9 | 0.005033 0.005011 0.005222 10 | 0.005495 0.005549 0.005758 11 | 0.005977 0.006114 0.006327 12 | 0.006474 0.006700 0.006910 13 | 0.006966 0.007288 0.007490 14 | 0.007509 0.007926 0.008068 15 | 0.008009 0.008515 0.008657 16 | 0.008495 0.009085 0.009245 17 | 0.008979 0.009645 0.009816 18 | 0.009486 0.010216 0.010406 19 | 0.010036 0.010772 0.010952 20 | 0.010596 0.011342 0.011516 21 | 0.011149 0.011911 0.012088 22 | 0.011703 0.012487 0.012660 23 | 0.012257 0.013073 0.013245 24 | 0.012822 0.013663 0.013822 25 | 0.013400 0.014274 0.014401 26 | 0.013999 0.014917 0.015002 27 | 0.014604 0.015559 0.015587 28 | 0.015218 0.016176 0.016138 29 | 0.015825 0.016780 0.016683 30 | 0.016431 0.017374 0.017216 31 | 0.017047 0.017970 0.017753 32 | 0.017664 0.018567 0.018297 33 | 0.018282 0.019157 0.018838 34 | 0.018900 0.019746 0.019379 35 | 0.019527 0.020343 0.019930 36 | 0.020157 0.020938 0.020483 37 | 0.020788 0.021533 0.021038 38 | 0.021419 0.022125 0.021590 39 | 0.022052 0.022718 0.022146 40 | 0.022691 0.023316 0.022710 41 | 0.023329 0.023910 0.023269 42 | 0.023968 0.024504 0.023834 43 | 0.024612 0.025101 0.024402 44 | 0.025255 0.025695 0.024970 45 | 0.025901 0.026292 0.025545 46 | 0.026543 0.026885 0.026117 47 | 0.027188 0.027481 0.026695 48 | 0.027832 0.028079 0.027279 49 | 0.028472 0.028674 0.027856 50 | 0.029114 0.029274 0.028442 51 | 0.029752 0.029871 0.029023 52 | 0.030384 0.030463 0.029599 53 | 0.031017 0.031061 0.030181 54 | 0.031646 0.031654 0.030753 55 | 0.032276 0.032252 0.031330 56 | 0.032910 0.032854 0.031908 57 | 0.033545 0.033457 0.032484 58 | 0.034189 0.034069 0.033069 59 | 0.034833 0.034679 0.033647 60 | 0.035488 0.035298 0.034233 61 | 0.036145 0.035919 0.034818 62 | 0.036804 0.036537 0.035394 63 | 0.037475 0.037167 0.035984 64 | 0.038141 0.037790 0.036560 65 | 0.038813 0.038420 0.037139 66 | 0.039465 0.039031 0.037777 67 | 0.040105 0.039631 0.038426 68 | 0.040763 0.040248 0.039081 69 | 0.041426 0.040871 0.039727 70 | 0.042100 0.041504 0.040372 71 | 0.042790 0.042156 0.041023 72 | 0.043485 0.042812 0.041662 73 | 0.044196 0.043486 0.042309 74 | 0.044912 0.044166 0.042948 75 | 0.045641 0.044860 0.043588 76 | 0.046376 0.045559 0.044263 77 | 0.047113 0.046259 0.044933 78 | 0.047868 0.046976 0.045613 79 | 0.048628 0.047694 0.046289 80 | 0.049393 0.048415 0.046964 81 | 0.050161 0.049138 0.047644 82 | 0.050916 0.049845 0.048328 83 | 0.051669 0.050550 0.049026 84 | 0.052424 0.051255 0.049725 85 | 0.053175 0.051955 0.050417 86 | 0.053937 0.052666 0.051123 87 | 0.054687 0.053366 0.051833 88 | 0.055445 0.054076 0.052553 89 | 0.056206 0.054792 0.053277 90 | 0.056967 0.055510 0.054000 91 | 0.057734 0.056239 0.054748 92 | 0.058503 0.056976 0.055498 93 | 0.059282 0.057733 0.056266 94 | 0.060061 0.058508 0.057063 95 | 0.060839 0.059293 0.057869 96 | 0.061629 0.060101 0.058701 97 | 0.062413 0.060918 0.059552 98 | 0.063200 0.061754 0.060423 99 | 0.063996 0.062610 0.061321 100 | 0.064792 0.063473 0.062229 101 | 0.065606 0.064352 0.063150 102 | 0.066431 0.065234 0.064074 103 | 0.067271 0.066121 0.064994 104 | 0.068129 0.067016 0.065922 105 | 0.068998 0.067915 0.066845 106 | 0.069883 0.068821 0.067777 107 | 0.070779 0.069733 0.068709 108 | 0.071686 0.070653 0.069650 109 | 0.072609 0.071588 0.070606 110 | 0.073540 0.072530 0.071566 111 | 0.074483 0.073485 0.072543 112 | 0.075435 0.074450 0.073530 113 | 0.076393 0.075424 0.074527 114 | 0.077368 0.076417 0.075548 115 | 0.078351 0.077422 0.076580 116 | 0.079353 0.078447 0.077635 117 | 0.080373 0.079493 0.078715 118 | 0.081407 0.080559 0.079816 119 | 0.082460 0.081652 0.080948 120 | 0.083527 0.082769 0.082108 121 | 0.084614 0.083912 0.083298 122 | 0.085719 0.085080 0.084517 123 | 0.086839 0.086269 0.085758 124 | 0.087978 0.087485 0.087036 125 | 0.089131 0.088720 0.088343 126 | 0.090298 0.089978 0.089684 127 | 0.091482 0.091261 0.091063 128 | 0.092680 0.092566 0.092474 129 | 0.093898 0.093900 0.093926 130 | 0.095134 0.095263 0.095415 131 | 0.096389 0.096656 0.096938 132 | 0.097667 0.098086 0.098498 133 | 0.098976 0.099565 0.100091 134 | 0.100324 0.101106 0.101728 135 | 0.101710 0.102701 0.103403 136 | 0.103139 0.104361 0.105119 137 | 0.104616 0.106098 0.106884 138 | 0.106135 0.107900 0.108684 139 | 0.107684 0.109737 0.110524 140 | 0.109247 0.111572 0.112397 141 | 0.110820 0.113391 0.114296 142 | 0.112410 0.115212 0.116236 143 | 0.114016 0.117033 0.118207 144 | 0.115639 0.118858 0.120218 145 | 0.117284 0.120698 0.122269 146 | 0.118952 0.122558 0.124355 147 | 0.120653 0.124453 0.126495 148 | 0.122378 0.126376 0.128673 149 | 0.124132 0.128331 0.130898 150 | 0.125918 0.130324 0.133176 151 | 0.127729 0.132347 0.135489 152 | 0.129574 0.134414 0.137860 153 | 0.131449 0.136520 0.140278 154 | 0.133355 0.138667 0.142749 155 | 0.135294 0.140863 0.145285 156 | 0.137251 0.143096 0.147865 157 | 0.139241 0.145393 0.150536 158 | 0.141253 0.147758 0.153305 159 | 0.143293 0.150189 0.156163 160 | 0.145369 0.152703 0.159135 161 | 0.147462 0.155288 0.162194 162 | 0.149587 0.157974 0.165385 163 | 0.151751 0.160747 0.168671 164 | 0.153962 0.163560 0.171981 165 | 0.156252 0.166418 0.175325 166 | 0.158594 0.169294 0.178646 167 | 0.161006 0.172220 0.182001 168 | 0.163481 0.175194 0.185389 169 | 0.166004 0.178193 0.188768 170 | 0.168602 0.181266 0.192220 171 | 0.171245 0.184381 0.195698 172 | 0.173942 0.187551 0.199232 173 | 0.176702 0.190787 0.202846 174 | 0.179488 0.194044 0.206470 175 | 0.182337 0.197362 0.210177 176 | 0.185214 0.200700 0.213902 177 | 0.188135 0.204083 0.217662 178 | 0.191124 0.207544 0.221512 179 | 0.194144 0.211036 0.225351 180 | 0.197245 0.214622 0.229291 181 | 0.200408 0.218275 0.233260 182 | 0.203643 0.222006 0.237258 183 | 0.206973 0.225845 0.241354 184 | 0.210355 0.229732 0.245422 185 | 0.213851 0.233747 0.249591 186 | 0.217441 0.237864 0.253803 187 | 0.221090 0.242039 0.258027 188 | 0.224802 0.246291 0.262382 189 | 0.228476 0.250498 0.266701 190 | 0.232183 0.254754 0.271141 191 | 0.235912 0.259046 0.275669 192 | 0.239647 0.263344 0.280201 193 | 0.243445 0.267718 0.284882 194 | 0.247246 0.272085 0.289536 195 | 0.251116 0.276526 0.294283 196 | 0.255052 0.281038 0.299122 197 | 0.258998 0.285543 0.303902 198 | 0.263041 0.290156 0.308830 199 | 0.267110 0.294780 0.313726 200 | 0.271246 0.299465 0.318685 201 | 0.275471 0.304243 0.323767 202 | 0.279694 0.308991 0.328745 203 | 0.284024 0.313857 0.333887 204 | 0.288394 0.318744 0.339008 205 | 0.292821 0.323676 0.344147 206 | 0.297363 0.328728 0.349436 207 | 0.301912 0.333744 0.354586 208 | 0.306588 0.338891 0.359903 209 | 0.311329 0.344087 0.365234 210 | 0.316124 0.349312 0.370544 211 | 0.321079 0.354704 0.376059 212 | 0.326048 0.360060 0.381416 213 | 0.331155 0.365554 0.386931 214 | 0.336375 0.371143 0.392511 215 | 0.341656 0.376755 0.398026 216 | 0.347141 0.382581 0.403798 217 | 0.352679 0.388407 0.409436 218 | 0.358391 0.394400 0.415232 219 | 0.364258 0.400532 0.421154 220 | 0.370197 0.406686 0.426980 221 | 0.376362 0.413067 0.433076 222 | 0.382588 0.419449 0.439047 223 | 0.388990 0.425995 0.445165 224 | 0.395611 0.432750 0.451487 225 | 0.402312 0.439505 0.457629 226 | 0.409320 0.446580 0.464123 227 | 0.416500 0.453786 0.470581 228 | 0.423898 0.461185 0.477137 229 | 0.431621 0.468908 0.484030 230 | 0.439454 0.476651 0.490726 231 | 0.447654 0.484751 0.497795 232 | 0.456115 0.493049 0.504925 233 | 0.464903 0.501590 0.512168 234 | 0.474170 0.510583 0.519870 235 | 0.483639 0.519668 0.527402 236 | 0.493626 0.529221 0.535394 237 | 0.504018 0.539085 0.543606 238 | 0.514784 0.549215 0.551950 239 | 0.526212 0.559929 0.560948 240 | 0.537931 0.570829 0.569972 241 | 0.550356 0.582319 0.579655 242 | 0.563426 0.594380 0.589910 243 | 0.576994 0.606861 0.600498 244 | 0.591523 0.620177 0.612096 245 | 0.606499 0.633875 0.624069 246 | 0.622640 0.648682 0.637476 247 | 0.639767 0.664444 0.652101 248 | 0.657662 0.680767 0.667120 249 | 0.677386 0.698592 0.683927 250 | 0.699448 0.718500 0.703392 251 | 0.723026 0.740104 0.724486 252 | 0.752971 0.767604 0.753891 253 | 0.782432 0.795133 0.781430 254 | 0.815813 0.826088 0.812815 255 | 0.872903 0.878322 0.870928 256 | 0.937368 0.940553 0.935474 257 | 1.000000 1.000000 1.000000 258 | -------------------------------------------------------------------------------- /camera_models/NikonD7000/jpg2raw_transform.txt: -------------------------------------------------------------------------------- 1 | 6 2 | 1.578706 -0.509131 -0.026729 3 | -0.129182 1.430037 -0.268639 4 | 0.026785 -0.554129 1.556603 5 | 3 6 | 2.078780 -0.513843 -0.059748 7 | -0.170102 1.443271 -0.600499 8 | 0.035270 -0.559258 3.479538 9 | 1.316762 1.009255 2.235341 10 | 4 11 | 3.669737 -0.518789 -0.032981 12 | -0.300287 1.457163 -0.331475 13 | 0.062263 -0.564641 1.920704 14 | 2.324523 1.018969 1.233907 15 | 9 16 | 3.236377 -0.514826 -0.037586 17 | -0.264826 1.446031 -0.377754 18 | 0.054910 -0.560327 2.188862 19 | 2.050019 1.011185 1.406179 20 | 10 21 | 3.484625 -0.518360 -0.034442 22 | -0.285140 1.455959 -0.346159 23 | 0.059122 -0.564174 2.005786 24 | 2.207267 1.018127 1.288567 25 | 11 26 | 4.023950 -0.520715 -0.031075 27 | -0.329271 1.462574 -0.312315 28 | 0.068272 -0.566737 1.809679 29 | 2.548892 1.022753 1.162582 30 | 14 31 | 2.892238 -0.509131 -0.054189 32 | -0.236666 1.430037 -0.544623 33 | 0.049071 -0.554129 3.155769 34 | 1.832031 1.000000 2.027344 35 | -------------------------------------------------------------------------------- /camera_models/NikonD7000/jpg2raw_validRange.txt: -------------------------------------------------------------------------------- 1 | 5 252 2 | -------------------------------------------------------------------------------- /camera_models/NikonD7000/raw2jpg_respFcns.txt: -------------------------------------------------------------------------------- 1 | 16400.000000 0.000000 0.000000 0.000000 2 | 0.000000 0.000000 0.000000 3 | 0.001304 0.001089 0.001547 4 | 0.002206 0.001898 0.002376 5 | 0.002950 0.002692 0.003020 6 | 0.003533 0.003316 0.003549 7 | 0.004035 0.003859 0.004047 8 | 0.004568 0.004470 0.004677 9 | 0.005033 0.005011 0.005222 10 | 0.005495 0.005549 0.005758 11 | 0.005977 0.006114 0.006327 12 | 0.006474 0.006700 0.006910 13 | 0.006966 0.007288 0.007490 14 | 0.007509 0.007926 0.008068 15 | 0.008009 0.008515 0.008657 16 | 0.008495 0.009085 0.009245 17 | 0.008979 0.009645 0.009816 18 | 0.009486 0.010216 0.010406 19 | 0.010036 0.010772 0.010952 20 | 0.010596 0.011342 0.011516 21 | 0.011149 0.011911 0.012088 22 | 0.011703 0.012487 0.012660 23 | 0.012257 0.013073 0.013245 24 | 0.012822 0.013663 0.013822 25 | 0.013400 0.014274 0.014401 26 | 0.013999 0.014917 0.015002 27 | 0.014604 0.015559 0.015587 28 | 0.015218 0.016176 0.016138 29 | 0.015825 0.016780 0.016683 30 | 0.016431 0.017374 0.017216 31 | 0.017047 0.017970 0.017753 32 | 0.017664 0.018567 0.018297 33 | 0.018282 0.019157 0.018838 34 | 0.018900 0.019746 0.019379 35 | 0.019527 0.020343 0.019930 36 | 0.020157 0.020938 0.020483 37 | 0.020788 0.021533 0.021038 38 | 0.021419 0.022125 0.021590 39 | 0.022052 0.022718 0.022146 40 | 0.022691 0.023316 0.022710 41 | 0.023329 0.023910 0.023269 42 | 0.023968 0.024504 0.023834 43 | 0.024612 0.025101 0.024402 44 | 0.025255 0.025695 0.024970 45 | 0.025901 0.026292 0.025545 46 | 0.026543 0.026885 0.026117 47 | 0.027188 0.027481 0.026695 48 | 0.027832 0.028079 0.027279 49 | 0.028472 0.028674 0.027856 50 | 0.029114 0.029274 0.028442 51 | 0.029752 0.029871 0.029023 52 | 0.030384 0.030463 0.029599 53 | 0.031017 0.031061 0.030181 54 | 0.031646 0.031654 0.030753 55 | 0.032276 0.032252 0.031330 56 | 0.032910 0.032854 0.031908 57 | 0.033545 0.033457 0.032484 58 | 0.034189 0.034069 0.033069 59 | 0.034833 0.034679 0.033647 60 | 0.035488 0.035298 0.034233 61 | 0.036145 0.035919 0.034818 62 | 0.036804 0.036537 0.035394 63 | 0.037475 0.037167 0.035984 64 | 0.038141 0.037790 0.036560 65 | 0.038813 0.038420 0.037139 66 | 0.039465 0.039031 0.037777 67 | 0.040105 0.039631 0.038426 68 | 0.040763 0.040248 0.039081 69 | 0.041426 0.040871 0.039727 70 | 0.042100 0.041504 0.040372 71 | 0.042790 0.042156 0.041023 72 | 0.043485 0.042812 0.041662 73 | 0.044196 0.043486 0.042309 74 | 0.044912 0.044166 0.042948 75 | 0.045641 0.044860 0.043588 76 | 0.046376 0.045559 0.044263 77 | 0.047113 0.046259 0.044933 78 | 0.047868 0.046976 0.045613 79 | 0.048628 0.047694 0.046289 80 | 0.049393 0.048415 0.046964 81 | 0.050161 0.049138 0.047644 82 | 0.050916 0.049845 0.048328 83 | 0.051669 0.050550 0.049026 84 | 0.052424 0.051255 0.049725 85 | 0.053175 0.051955 0.050417 86 | 0.053937 0.052666 0.051123 87 | 0.054687 0.053366 0.051833 88 | 0.055445 0.054076 0.052553 89 | 0.056206 0.054792 0.053277 90 | 0.056967 0.055510 0.054000 91 | 0.057734 0.056239 0.054748 92 | 0.058503 0.056976 0.055498 93 | 0.059282 0.057733 0.056266 94 | 0.060061 0.058508 0.057063 95 | 0.060839 0.059293 0.057869 96 | 0.061629 0.060101 0.058701 97 | 0.062413 0.060918 0.059552 98 | 0.063200 0.061754 0.060423 99 | 0.063996 0.062610 0.061321 100 | 0.064792 0.063473 0.062229 101 | 0.065606 0.064352 0.063150 102 | 0.066431 0.065234 0.064074 103 | 0.067271 0.066121 0.064994 104 | 0.068129 0.067016 0.065922 105 | 0.068998 0.067915 0.066845 106 | 0.069883 0.068821 0.067777 107 | 0.070779 0.069733 0.068709 108 | 0.071686 0.070653 0.069650 109 | 0.072609 0.071588 0.070606 110 | 0.073540 0.072530 0.071566 111 | 0.074483 0.073485 0.072543 112 | 0.075435 0.074450 0.073530 113 | 0.076393 0.075424 0.074527 114 | 0.077368 0.076417 0.075548 115 | 0.078351 0.077422 0.076580 116 | 0.079353 0.078447 0.077635 117 | 0.080373 0.079493 0.078715 118 | 0.081407 0.080559 0.079816 119 | 0.082460 0.081652 0.080948 120 | 0.083527 0.082769 0.082108 121 | 0.084614 0.083912 0.083298 122 | 0.085719 0.085080 0.084517 123 | 0.086839 0.086269 0.085758 124 | 0.087978 0.087485 0.087036 125 | 0.089131 0.088720 0.088343 126 | 0.090298 0.089978 0.089684 127 | 0.091482 0.091261 0.091063 128 | 0.092680 0.092566 0.092474 129 | 0.093898 0.093900 0.093926 130 | 0.095134 0.095263 0.095415 131 | 0.096389 0.096656 0.096938 132 | 0.097667 0.098086 0.098498 133 | 0.098976 0.099565 0.100091 134 | 0.100324 0.101106 0.101728 135 | 0.101710 0.102701 0.103403 136 | 0.103139 0.104361 0.105119 137 | 0.104616 0.106098 0.106884 138 | 0.106135 0.107900 0.108684 139 | 0.107684 0.109737 0.110524 140 | 0.109247 0.111572 0.112397 141 | 0.110820 0.113391 0.114296 142 | 0.112410 0.115212 0.116236 143 | 0.114016 0.117033 0.118207 144 | 0.115639 0.118858 0.120218 145 | 0.117284 0.120698 0.122269 146 | 0.118952 0.122558 0.124355 147 | 0.120653 0.124453 0.126495 148 | 0.122378 0.126376 0.128673 149 | 0.124132 0.128331 0.130898 150 | 0.125918 0.130324 0.133176 151 | 0.127729 0.132347 0.135489 152 | 0.129574 0.134414 0.137860 153 | 0.131449 0.136520 0.140278 154 | 0.133355 0.138667 0.142749 155 | 0.135294 0.140863 0.145285 156 | 0.137251 0.143096 0.147865 157 | 0.139241 0.145393 0.150536 158 | 0.141253 0.147758 0.153305 159 | 0.143293 0.150189 0.156163 160 | 0.145369 0.152703 0.159135 161 | 0.147462 0.155288 0.162194 162 | 0.149587 0.157974 0.165385 163 | 0.151751 0.160747 0.168671 164 | 0.153962 0.163560 0.171981 165 | 0.156252 0.166418 0.175325 166 | 0.158594 0.169294 0.178646 167 | 0.161006 0.172220 0.182001 168 | 0.163481 0.175194 0.185389 169 | 0.166004 0.178193 0.188768 170 | 0.168602 0.181266 0.192220 171 | 0.171245 0.184381 0.195698 172 | 0.173942 0.187551 0.199232 173 | 0.176702 0.190787 0.202846 174 | 0.179488 0.194044 0.206470 175 | 0.182337 0.197362 0.210177 176 | 0.185214 0.200700 0.213902 177 | 0.188135 0.204083 0.217662 178 | 0.191124 0.207544 0.221512 179 | 0.194144 0.211036 0.225351 180 | 0.197245 0.214622 0.229291 181 | 0.200408 0.218275 0.233260 182 | 0.203643 0.222006 0.237258 183 | 0.206973 0.225845 0.241354 184 | 0.210355 0.229732 0.245422 185 | 0.213851 0.233747 0.249591 186 | 0.217441 0.237864 0.253803 187 | 0.221090 0.242039 0.258027 188 | 0.224802 0.246291 0.262382 189 | 0.228476 0.250498 0.266701 190 | 0.232183 0.254754 0.271141 191 | 0.235912 0.259046 0.275669 192 | 0.239647 0.263344 0.280201 193 | 0.243445 0.267718 0.284882 194 | 0.247246 0.272085 0.289536 195 | 0.251116 0.276526 0.294283 196 | 0.255052 0.281038 0.299122 197 | 0.258998 0.285543 0.303902 198 | 0.263041 0.290156 0.308830 199 | 0.267110 0.294780 0.313726 200 | 0.271246 0.299465 0.318685 201 | 0.275471 0.304243 0.323767 202 | 0.279694 0.308991 0.328745 203 | 0.284024 0.313857 0.333887 204 | 0.288394 0.318744 0.339008 205 | 0.292821 0.323676 0.344147 206 | 0.297363 0.328728 0.349436 207 | 0.301912 0.333744 0.354586 208 | 0.306588 0.338891 0.359903 209 | 0.311329 0.344087 0.365234 210 | 0.316124 0.349312 0.370544 211 | 0.321079 0.354704 0.376059 212 | 0.326048 0.360060 0.381416 213 | 0.331155 0.365554 0.386931 214 | 0.336375 0.371143 0.392511 215 | 0.341656 0.376755 0.398026 216 | 0.347141 0.382581 0.403798 217 | 0.352679 0.388407 0.409436 218 | 0.358391 0.394400 0.415232 219 | 0.364258 0.400532 0.421154 220 | 0.370197 0.406686 0.426980 221 | 0.376362 0.413067 0.433076 222 | 0.382588 0.419449 0.439047 223 | 0.388990 0.425995 0.445165 224 | 0.395611 0.432750 0.451487 225 | 0.402312 0.439505 0.457629 226 | 0.409320 0.446580 0.464123 227 | 0.416500 0.453786 0.470581 228 | 0.423898 0.461185 0.477137 229 | 0.431621 0.468908 0.484030 230 | 0.439454 0.476651 0.490726 231 | 0.447654 0.484751 0.497795 232 | 0.456115 0.493049 0.504925 233 | 0.464903 0.501590 0.512168 234 | 0.474170 0.510583 0.519870 235 | 0.483639 0.519668 0.527402 236 | 0.493626 0.529221 0.535394 237 | 0.504018 0.539085 0.543606 238 | 0.514784 0.549215 0.551950 239 | 0.526212 0.559929 0.560948 240 | 0.537931 0.570829 0.569972 241 | 0.550356 0.582319 0.579655 242 | 0.563426 0.594380 0.589910 243 | 0.576994 0.606861 0.600498 244 | 0.591523 0.620177 0.612096 245 | 0.606499 0.633875 0.624069 246 | 0.622640 0.648682 0.637476 247 | 0.639767 0.664444 0.652101 248 | 0.657662 0.680767 0.667120 249 | 0.677386 0.698592 0.683927 250 | 0.699448 0.718500 0.703392 251 | 0.723026 0.740104 0.724486 252 | 0.752971 0.767604 0.753891 253 | 0.782432 0.795133 0.781430 254 | 0.815813 0.826088 0.812815 255 | 0.872903 0.878322 0.870928 256 | 0.937368 0.940553 0.935474 257 | 1.000000 1.000000 1.000000 258 | -------------------------------------------------------------------------------- /camera_models/NikonD7000/raw2jpg_transform.txt: -------------------------------------------------------------------------------- 1 | 6 2 | 1.578706 -0.509131 -0.026729 3 | -0.129182 1.430037 -0.268639 4 | 0.026785 -0.554129 1.556603 5 | 3 6 | 2.078780 -0.513843 -0.059748 7 | -0.170102 1.443271 -0.600499 8 | 0.035270 -0.559258 3.479538 9 | 1.316762 1.009255 2.235341 10 | 4 11 | 3.669737 -0.518789 -0.032981 12 | -0.300287 1.457163 -0.331475 13 | 0.062263 -0.564641 1.920704 14 | 2.324523 1.018969 1.233907 15 | 9 16 | 3.236377 -0.514826 -0.037586 17 | -0.264826 1.446031 -0.377754 18 | 0.054910 -0.560327 2.188862 19 | 2.050019 1.011185 1.406179 20 | 10 21 | 3.484625 -0.518360 -0.034442 22 | -0.285140 1.455959 -0.346159 23 | 0.059122 -0.564174 2.005786 24 | 2.207267 1.018127 1.288567 25 | 11 26 | 4.023950 -0.520715 -0.031075 27 | -0.329271 1.462574 -0.312315 28 | 0.068272 -0.566737 1.809679 29 | 2.548892 1.022753 1.162582 30 | 14 31 | 2.892238 -0.509131 -0.054189 32 | -0.236666 1.430037 -0.544623 33 | 0.049071 -0.554129 3.155769 34 | 1.832031 1.000000 2.027344 35 | -------------------------------------------------------------------------------- /camera_models/NikonD7000/raw2jpg_validRange.txt: -------------------------------------------------------------------------------- 1 | 5 252 2 | -------------------------------------------------------------------------------- /camera_models/README.txt: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # 3 | # Camera Pipeline Models 4 | # 5 | ##################################################################### 6 | 7 | 8 | ##################################################################### 9 | # Description 10 | ##################################################################### 11 | 12 | This directory contains model parameters for various camera pipelines. 13 | Models were created with the methodology shown in "A New In-Camera 14 | Imaging Model for Color Computer Vision and its Application". More 15 | models can be found at the links below. 16 | 17 | 18 | ##################################################################### 19 | # Useful Links 20 | ##################################################################### 21 | 22 | Project page 23 | http://www.comp.nus.edu.sg/~brown/radiometric_calibration/ 24 | 25 | Model zoo 26 | http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/nikon_sets.html 27 | 28 | Model format readme 29 | http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/Model_param/readme.pdf 30 | -------------------------------------------------------------------------------- /imgs/NikonD7000FL/DSC_0916.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/imgs/NikonD7000FL/DSC_0916.JPG -------------------------------------------------------------------------------- /imgs/NikonD7000FL/DSC_0916.NEF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/imgs/NikonD7000FL/DSC_0916.NEF -------------------------------------------------------------------------------- /imgs/NikonD7000FL/DSC_0916.NEF.demos_3C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/imgs/NikonD7000FL/DSC_0916.NEF.demos_3C.png -------------------------------------------------------------------------------- /imgs/NikonD7000FL/DSC_0916.NEF.raw_1C.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/imgs/NikonD7000FL/DSC_0916.NEF.raw_1C.tiff -------------------------------------------------------------------------------- /imgs/NikonD7000FL/DSC_0916.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/imgs/NikonD7000FL/DSC_0916.png -------------------------------------------------------------------------------- /imgs/README.txt: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # 3 | # Camera Pipeline Sample Images 4 | # 5 | ##################################################################### 6 | 7 | 8 | ##################################################################### 9 | # Description 10 | ##################################################################### 11 | 12 | This directory currently contains only images captured by a Nikon 13 | D7000 camera using the normal setting and the Fl (flourescent) 14 | color transform. Three brightness levels are provided, more 15 | can be found online. NEF files are raw, JPG files are processed by 16 | the camera, and the tiff files are the NEF files converted to tif 17 | format to be more easily read by Matlab. This conversion was done 18 | with a script contained within the src/Matlab/ directory. 19 | 20 | 21 | ##################################################################### 22 | # Useful Links 23 | ##################################################################### 24 | 25 | Project page 26 | http://www.comp.nus.edu.sg/~brown/radiometric_calibration/ 27 | 28 | Datasets 29 | * http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/nikon_sets.html 30 | * http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/other_sets.html 31 | * http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/other_sets.html 32 | 33 | The D7000 normal florescent images 34 | http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/JPG_RAW_org/NikonD7000_Indoor20110507_4s/N/Fl.zip 35 | -------------------------------------------------------------------------------- /src/Halide/ImgPipeConfig.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////// 2 | // Image Pipeline Halide Configuration File 3 | /////////////////////////////////////////////////////////////// 4 | // 5 | // This file defines the parameters associated with the camera 6 | // model and the input images. These parameters can be found 7 | // within the camera model files themselves. The format of 8 | // the camera model files is described at the link below. 9 | // 10 | // Model format readme: 11 | // http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/Model_param/readme.pdf 12 | // 13 | /////////////////////////////////////////////////////////////// 14 | 15 | /////////////////////////////////////////////////////////////// 16 | // Input Image Parameters 17 | /////////////////////////////////////////////////////////////// 18 | 19 | // Demosaiced raw input (to forward pipeline) 20 | char demosaiced_image[] = 21 | "../../imgs/NikonD7000FL/DSC_0916.NEF.demos_3C.png"; 22 | 23 | // Jpeg input to backward pipeline. Must be converted to png 24 | char jpg_image[] = 25 | "../../imgs/NikonD7000FL/DSC_0916.png"; 26 | 27 | // Process the full image? 28 | // true: process the full image, ignore patch parameters 29 | // false: process only the patch defined by the patch parameters 30 | bool full = false; 31 | 32 | /////////////////////////////////////////////////////////////// 33 | // Patch Parameters 34 | /////////////////////////////////////////////////////////////// 35 | 36 | // The width and height of the patch (in pixels) 37 | int patchsize = 1; 38 | 39 | // The x and y location of the upper left corner 40 | // of the patch to be processed 41 | int xstart = 551; 42 | int ystart = 2751; 43 | 44 | /////////////////////////////////////////////////////////////// 45 | // Camera Model Parameters 46 | /////////////////////////////////////////////////////////////// 47 | 48 | // Path to the camera model to be used 49 | char cam_model_path[] = 50 | "../../camera_models/NikonD7000/"; 51 | 52 | // White balance index (select white balance from transform file) 53 | // The first white balance in the file has a wb_index of 1 54 | // For more information on model format see the readme 55 | int wb_index = 56 | 6; 57 | 58 | // Number of control points 59 | const int num_ctrl_pts = 60 | 3702; 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/Halide/ImgPipe_Halide.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////////////// 2 | // Image Processing Pipeline 3 | // 4 | // This is a Halide implementation of a pre-learned image 5 | // processing model. A description of the model can be found in 6 | // "A New In-Camera Imaging Model for Color Computer Vision 7 | // and its Application" by Seon Joo Kim, Hai Ting Lin, 8 | // Michael Brown, et al. Code for learning a new model can 9 | // be found at the original project page. This particular 10 | // implementation was written by Mark Buckler. 11 | // 12 | // Original Project Page: 13 | // http://www.comp.nus.edu.sg/~brown/radiometric_calibration/ 14 | // 15 | // Model Format Readme: 16 | // http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/Model_param/readme.pdf 17 | // 18 | ///////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | #include "Halide.h" 21 | #include "ImgPipeConfig.h" 22 | #include "LoadCamModel.h" 23 | #include "MatrixOps.h" 24 | #include 25 | #include 26 | #include "halide_image_io.h" 27 | #include "clock.h" 28 | 29 | // Function prototypes 30 | int run_pipeline(bool direction); 31 | 32 | 33 | int main(int argc, char **argv) { 34 | using namespace std; 35 | 36 | printf("Starting script. Note that processing may take several minutes for large images\n"); 37 | 38 | // Run forward pipeline 39 | printf("Running forward pipeline...\n"); 40 | run_pipeline(true); 41 | printf("Forward pipeline complete\n"); 42 | 43 | // Run backward pipeline 44 | printf("Running backward pipeline...\n"); 45 | run_pipeline(false); 46 | printf("Backward pipeline complete\n"); 47 | 48 | printf("Success!\n"); 49 | return 0; 50 | } 51 | 52 | 53 | // Reversible pipeline function 54 | int run_pipeline(bool direction) { 55 | 56 | /////////////////////////////////////////////////////////////////////////////////////// 57 | // Import and format model data 58 | 59 | using namespace std; 60 | 61 | // Declare model parameters 62 | vector> Ts, Tw, TsTw; 63 | vector> ctrl_pts, weights, coefs; 64 | vector> rev_tone; 65 | 66 | // Load model parameters from file 67 | // NOTE: Ts, Tw, and TsTw read only forward data 68 | // ctrl_pts, weights, and coefs are either forward or backward 69 | // tone mapping is always backward 70 | // This is due to the the camera model format 71 | Ts = get_Ts (cam_model_path); 72 | Tw = get_Tw (cam_model_path, wb_index); 73 | TsTw = get_TsTw (cam_model_path, wb_index); 74 | ctrl_pts = get_ctrl_pts (cam_model_path, num_ctrl_pts, direction); 75 | weights = get_weights (cam_model_path, num_ctrl_pts, direction); 76 | coefs = get_coefs (cam_model_path, num_ctrl_pts, direction); 77 | rev_tone = get_rev_tone (cam_model_path); 78 | 79 | // Take the transpose of the color map and white balance transform for later use 80 | vector> TsTw_tran = transpose_mat (TsTw); 81 | 82 | // If we are performing a backward implementation of the pipeline, 83 | // take the inverse of TsTw_tran 84 | if (direction == 0) { 85 | TsTw_tran = inv_3x3mat(TsTw_tran); 86 | } 87 | 88 | using namespace Halide; 89 | using namespace Halide::Tools; 90 | 91 | // Convert control points to a Halide image 92 | int width = ctrl_pts[0].size(); 93 | int length = ctrl_pts.size(); 94 | Image ctrl_pts_h(width,length); 95 | for (int y=0; y weights_h(width,length); 104 | for (int y=0; y rev_tone_h(width,length); 113 | for (int y=0; y input; 127 | if (direction == 1) { 128 | // If using forward pipeline 129 | input = load_image(demosaiced_image); 130 | } else { 131 | // If using backward pipeline 132 | input = load_image(jpg_image); 133 | } 134 | 135 | // Initialize patch 136 | Image in_patch; 137 | 138 | // Define simple copying function 139 | Func pixel_copy("pixel_copy"); 140 | pixel_copy(x,y,c) = input(x,y,c); 141 | 142 | // Resize the input if not processing full image 143 | if (full == true) { 144 | // Define the patch as the full image 145 | in_patch = input; 146 | } else { 147 | // Copy the subset of the image into the patch 148 | Image temp(patchsize,patchsize,3); 149 | temp.set_min(xstart,ystart); 150 | in_patch = temp; 151 | pixel_copy.realize(in_patch); 152 | } 153 | 154 | /////////////////////////////////////////////////////////////////////////////////////// 155 | // Halide Funcs for camera pipeline 156 | 157 | // Cast input to float and scale according to its 8 bit input format 158 | Func scale("scale"); 159 | scale(x,y,c) = cast(in_patch(x,y,c))/256; 160 | 161 | // FORWARD FUNCS ////////////////////////////////////////////////////////////////////// 162 | 163 | // Color map and white balance transform 164 | Func transform("transform"); 165 | transform(x,y,c) = select( 166 | // Perform matrix multiplication, set min of 0 167 | c == 0, scale(x,y,0)*TsTw_tran[0][0] 168 | + scale(x,y,1)*TsTw_tran[1][0] 169 | + scale(x,y,2)*TsTw_tran[2][0], 170 | c == 1, scale(x,y,0)*TsTw_tran[0][1] 171 | + scale(x,y,1)*TsTw_tran[1][1] 172 | + scale(x,y,2)*TsTw_tran[2][1], 173 | scale(x,y,0)*TsTw_tran[0][2] 174 | + scale(x,y,1)*TsTw_tran[1][2] 175 | + scale(x,y,2)*TsTw_tran[2][2]); 176 | 177 | // Weighted radial basis function for gamut mapping 178 | Func rbf_ctrl_pts("rbf_ctrl_pts"); 179 | // Initialization with all zero 180 | rbf_ctrl_pts(x,y,c) = cast(0); 181 | // Index to iterate with 182 | RDom idx(0,num_ctrl_pts); 183 | // Loop code 184 | // Subtract the vectors 185 | Expr red_sub = transform(x,y,0) - ctrl_pts_h(0,idx); 186 | Expr green_sub = transform(x,y,1) - ctrl_pts_h(1,idx); 187 | Expr blue_sub = transform(x,y,2) - ctrl_pts_h(2,idx); 188 | // Take the L2 norm to get the distance 189 | Expr dist = sqrt( red_sub*red_sub + green_sub*green_sub + blue_sub*blue_sub ); 190 | // Update persistant loop variables 191 | rbf_ctrl_pts(x,y,c) = select( c == 0, rbf_ctrl_pts(x,y,c) + (weights_h(0,idx) * dist), 192 | c == 1, rbf_ctrl_pts(x,y,c) + (weights_h(1,idx) * dist), 193 | rbf_ctrl_pts(x,y,c) + (weights_h(2,idx) * dist)); 194 | 195 | // Add on the biases for the RBF 196 | Func rbf_biases("rbf_biases"); 197 | rbf_biases(x,y,c) = max( select( 198 | c == 0, rbf_ctrl_pts(x,y,0) + coefs[0][0] + coefs[1][0]*transform(x,y,0) + 199 | coefs[2][0]*transform(x,y,1) + coefs[3][0]*transform(x,y,2), 200 | c == 1, rbf_ctrl_pts(x,y,1) + coefs[0][1] + coefs[1][1]*transform(x,y,0) + 201 | coefs[2][1]*transform(x,y,1) + coefs[3][1]*transform(x,y,2), 202 | rbf_ctrl_pts(x,y,2) + coefs[0][2] + coefs[1][2]*transform(x,y,0) + 203 | coefs[2][2]*transform(x,y,1) + coefs[3][2]*transform(x,y,2)) 204 | , 0); 205 | 206 | // Forward tone mapping 207 | Func tonemap("tonemap"); 208 | RDom idx2(0,256); 209 | // Theres a lot in this one line! Functionality wise it finds the entry in 210 | // the reverse tone mapping function which is closest to the value found by 211 | // gamut mapping. The output is then cast to uint8 for output. Effectively 212 | // it reverses the reverse tone mapping function. 213 | tonemap(x,y,c) = cast(argmin( abs( rev_tone_h(c,idx2) - rbf_biases(x,y,c) ) )[0]); 214 | 215 | 216 | // BACKWARD FUNCS ///////////////////////////////////////////////////////////////////// 217 | 218 | // Backward tone mapping 219 | Func rev_tonemap("rev_tonemap"); 220 | Expr rev_tone_idx = cast(scale(x,y,c) * 256.0f); 221 | rev_tonemap(x,y,c) = rev_tone_h(c,rev_tone_idx) ; 222 | 223 | // Weighted radial basis function for gamut mapping 224 | Func rev_rbf_ctrl_pts("rev_rbf_ctrl_pts"); 225 | // Initialization with all zero 226 | rev_rbf_ctrl_pts(x,y,c) = cast(0); 227 | // Index to iterate with 228 | RDom revidx(0,num_ctrl_pts); 229 | // Loop code 230 | // Subtract the vectors 231 | Expr revred_sub = rev_tonemap(x,y,0) - ctrl_pts_h(0,revidx); 232 | Expr revgreen_sub = rev_tonemap(x,y,1) - ctrl_pts_h(1,revidx); 233 | Expr revblue_sub = rev_tonemap(x,y,2) - ctrl_pts_h(2,revidx); 234 | // Take the L2 norm to get the distance 235 | Expr revdist = sqrt( revred_sub*revred_sub + 236 | revgreen_sub*revgreen_sub + 237 | revblue_sub*revblue_sub ); 238 | // Update persistant loop variables 239 | rev_rbf_ctrl_pts(x,y,c) = select( c == 0, rev_rbf_ctrl_pts(x,y,c) + (weights_h(0,revidx) * revdist), 240 | c == 1, rev_rbf_ctrl_pts(x,y,c) + (weights_h(1,revidx) * revdist), 241 | rev_rbf_ctrl_pts(x,y,c) + (weights_h(2,revidx) * revdist)); 242 | 243 | // Add on the biases for the RBF 244 | Func rev_rbf_biases("rev_rbf_biases"); 245 | rev_rbf_biases(x,y,c) = max( select( 246 | c == 0, rev_rbf_ctrl_pts(x,y,0) + coefs[0][0] + coefs[1][0]*rev_tonemap(x,y,0) + 247 | coefs[2][0]*rev_tonemap(x,y,1) + coefs[3][0]*rev_tonemap(x,y,2), 248 | c == 1, rev_rbf_ctrl_pts(x,y,1) + coefs[0][1] + coefs[1][1]*rev_tonemap(x,y,0) + 249 | coefs[2][1]*rev_tonemap(x,y,1) + coefs[3][1]*rev_tonemap(x,y,2), 250 | rev_rbf_ctrl_pts(x,y,2) + coefs[0][2] + coefs[1][2]*rev_tonemap(x,y,0) + 251 | coefs[2][2]*rev_tonemap(x,y,1) + coefs[3][2]*rev_tonemap(x,y,2)) 252 | , 0); 253 | 254 | // Reverse color map and white balance transform 255 | Func rev_transform("rev_transform"); 256 | rev_transform(x,y,c) = cast( 256.0f * max( select( 257 | // Perform matrix multiplication, set min of 0 258 | c == 0, rev_rbf_biases(x,y,0)*TsTw_tran[0][0] 259 | + rev_rbf_biases(x,y,1)*TsTw_tran[1][0] 260 | + rev_rbf_biases(x,y,2)*TsTw_tran[2][0], 261 | c == 1, rev_rbf_biases(x,y,0)*TsTw_tran[0][1] 262 | + rev_rbf_biases(x,y,1)*TsTw_tran[1][1] 263 | + rev_rbf_biases(x,y,2)*TsTw_tran[2][1], 264 | rev_rbf_biases(x,y,0)*TsTw_tran[0][2] 265 | + rev_rbf_biases(x,y,1)*TsTw_tran[1][2] 266 | + rev_rbf_biases(x,y,2)*TsTw_tran[2][2]) 267 | , 0) ); 268 | 269 | //////////////////////////////////////////////////////////////////////// 270 | // Scheduling 271 | 272 | // Loop over color (c) first, unroll this loop 273 | transform.reorder(c,x,y).bound(c,0,3).unroll(c); 274 | rbf_ctrl_pts.reorder(c,x,y).bound(c,0,3).unroll(c); 275 | rbf_biases.reorder(c,x,y).bound(c,0,3).unroll(c); 276 | tonemap.reorder(c,x,y).bound(c,0,3).unroll(c); 277 | 278 | rev_transform.reorder(c,x,y).bound(c,0,3).unroll(c); 279 | rev_rbf_ctrl_pts.reorder(c,x,y).bound(c,0,3).unroll(c); 280 | rev_rbf_biases.reorder(c,x,y).bound(c,0,3).unroll(c); 281 | rev_tonemap.reorder(c,x,y).bound(c,0,3).unroll(c); 282 | 283 | // Go pixel by pixel, store intermediate values for later use 284 | transform.store_root().compute_at(tonemap,x); 285 | rbf_ctrl_pts.store_root().compute_at(tonemap,x); 286 | rbf_biases.store_root().compute_at(tonemap,x); 287 | 288 | rev_tonemap.store_root().compute_at(rev_transform,x); 289 | rev_rbf_ctrl_pts.store_root().compute_at(rev_transform,x); 290 | rev_rbf_biases.store_root().compute_at(rev_transform,x); 291 | 292 | // Use the just in time compiler 293 | tonemap.compile_jit(); 294 | rev_tonemap.compile_jit(); 295 | 296 | //////////////////////////////////////////////////////////////////////// 297 | // Realization (actual computation) 298 | 299 | double t1, t2; 300 | t1 = current_time(); 301 | 302 | Image output; 303 | // Resize the input if not processing full image 304 | if (full == true) { 305 | // patch as the full image 306 | if (direction == 1) { 307 | // forward pipeline 308 | output = tonemap.realize(in_patch.width(), 309 | in_patch.height(), 310 | in_patch.channels()); 311 | } else { 312 | // backward pipeline 313 | output = rev_transform.realize(in_patch.width(), 314 | in_patch.height(), 315 | in_patch.channels()); 316 | } 317 | } else { 318 | // Copy the subset of the image into the patch 319 | Image temp(patchsize,patchsize,3); 320 | temp.set_min(xstart,ystart); 321 | output = temp; 322 | if (direction == 1) { 323 | // forward pipeline 324 | tonemap.realize(output); 325 | } else { 326 | // backward pipeline 327 | rev_transform.realize(output); 328 | } 329 | } 330 | 331 | t2 = current_time(); 332 | 333 | printf("Processing time = %1.4f milliseconds\n",t2-t1); 334 | 335 | //////////////////////////////////////////////////////////////////////// 336 | // Save the output 337 | 338 | save_image(output, "output.png"); 339 | 340 | return 0; 341 | } 342 | 343 | -------------------------------------------------------------------------------- /src/Halide/LoadCamModel.cpp: -------------------------------------------------------------------------------- 1 | #include "LoadCamModel.h" 2 | 3 | using namespace std; 4 | 5 | // Get color space transform 6 | vector> get_Ts(char* cam_model_path) { 7 | 8 | vector> Ts; 9 | string line; 10 | int line_idx = 0; 11 | 12 | // Open file for reading 13 | ifstream file(cam_model_path+string("raw2jpg_transform.txt")); 14 | 15 | // Read a line at a time 16 | while(getline(file, line)) 17 | { 18 | vector lineData, temp; 19 | stringstream lineStream(line); 20 | float value; 21 | // Read one value at a time from the line 22 | while(lineStream >> value) 23 | { 24 | lineData.push_back(value); 25 | } 26 | if (line_idx>=1 && line_idx<=3) { 27 | for (int i=0; i<3; i++) { 28 | temp.push_back(lineData[i]); 29 | } 30 | Ts.push_back(temp); 31 | } 32 | line_idx = line_idx + 1; 33 | } 34 | 35 | return Ts; 36 | 37 | } 38 | 39 | // Get white balance transform 40 | vector> get_Tw(char* cam_model_path, int wb_index) { 41 | 42 | vector> Tw; 43 | string line; 44 | int line_idx = 0; 45 | 46 | // Calculate base for the white balance transform selected 47 | // For more details see the camera model readme 48 | int wb_base = 8 + 5*(wb_index-1); 49 | 50 | // Open file for reading 51 | ifstream file(cam_model_path+string("raw2jpg_transform.txt")); 52 | 53 | // Read a line at a time 54 | while(getline(file, line)) 55 | { 56 | vector lineData, temp; 57 | stringstream lineStream(line); 58 | float value; 59 | // Read one value at a time from the line 60 | while(lineStream >> value) 61 | { 62 | lineData.push_back(value); 63 | } 64 | // If this is the line with the white balance 65 | if (line_idx==wb_base) { 66 | // Convert the white balance vector into a diagaonal matrix 67 | for (int i=0; i<3; i++) { 68 | for (int j=0; j<3; j++) { 69 | if (i==j) { temp.push_back(lineData[i]); } 70 | else { temp.push_back(0.0); } 71 | } 72 | Tw.push_back(temp); 73 | temp.clear(); 74 | } 75 | 76 | } 77 | line_idx = line_idx + 1; 78 | } 79 | 80 | return Tw; 81 | 82 | } 83 | 84 | // Get combined transforms for checking 85 | vector> get_TsTw(char* cam_model_path, int wb_index) { 86 | 87 | vector> TsTw; 88 | string line; 89 | int line_idx = 0; 90 | 91 | // Calculate base for the white balance transform selected 92 | // For more details see the camera model readme 93 | int wb_base = 5 + 5*(wb_index-1); 94 | 95 | // Open file for reading 96 | ifstream file(cam_model_path+string("raw2jpg_transform.txt")); 97 | 98 | // Read a line at a time 99 | while(getline(file, line)) 100 | { 101 | vector lineData, temp; 102 | stringstream lineStream(line); 103 | float value; 104 | // Read one value at a time from the line 105 | while(lineStream >> value) 106 | { 107 | lineData.push_back(value); 108 | } 109 | if (line_idx>=wb_base && line_idx<=(wb_base+2)) { 110 | for (int i=0; i<3; i++) { 111 | temp.push_back(lineData[i]); 112 | } 113 | TsTw.push_back(temp); 114 | } 115 | line_idx = line_idx + 1; 116 | } 117 | 118 | return TsTw; 119 | 120 | } 121 | 122 | // Get control points 123 | vector> get_ctrl_pts(char* cam_model_path, int num_cntrl_pts, bool direction) { 124 | 125 | vector> ctrl_pnts; 126 | string line, directionfile; 127 | int line_idx = 0; 128 | 129 | // Open file for reading 130 | if (direction==1) { 131 | // Forward pipeline 132 | directionfile = string("raw2jpg_ctrlPoints.txt"); 133 | } else { 134 | // Backward pipeline 135 | directionfile = string("jpg2raw_ctrlPoints.txt"); 136 | } 137 | ifstream file(cam_model_path+directionfile); 138 | 139 | // Read a line at a time 140 | while(getline(file, line)) 141 | { 142 | vector lineData, temp; 143 | stringstream lineStream(line); 144 | float value; 145 | // Read one value at a time from the line 146 | while(lineStream >> value) 147 | { 148 | lineData.push_back(value); 149 | } 150 | if (line_idx>=1 && line_idx<=num_cntrl_pts) { 151 | for (int i=0; i<3; i++) { 152 | temp.push_back(lineData[i]); 153 | } 154 | ctrl_pnts.push_back(temp); 155 | } 156 | line_idx = line_idx + 1; 157 | } 158 | 159 | return ctrl_pnts; 160 | 161 | } 162 | 163 | // Get weights 164 | vector> get_weights(char* cam_model_path, int num_cntrl_pts, bool direction) { 165 | 166 | vector> weights; 167 | string line, directionfile; 168 | int line_idx = 0; 169 | 170 | // Open file for reading 171 | if (direction==1) { 172 | // Forward pipeline 173 | directionfile = string("raw2jpg_coefs.txt"); 174 | } else { 175 | // Backward pipeline 176 | directionfile = string("jpg2raw_coefs.txt"); 177 | } 178 | ifstream file(cam_model_path+directionfile); 179 | 180 | // Read a line at a time 181 | while(getline(file, line)) 182 | { 183 | vector lineData, temp; 184 | stringstream lineStream(line); 185 | float value; 186 | // Read one value at a time from the line 187 | while(lineStream >> value) 188 | { 189 | lineData.push_back(value); 190 | } 191 | if (line_idx>=1 && line_idx<=num_cntrl_pts) { 192 | for (int i=0; i<3; i++) { 193 | temp.push_back(lineData[i]); 194 | } 195 | weights.push_back(temp); 196 | } 197 | line_idx = line_idx + 1; 198 | } 199 | 200 | return weights; 201 | 202 | } 203 | 204 | // Get coeficients 205 | vector> get_coefs(char* cam_model_path, int num_cntrl_pts, bool direction) { 206 | 207 | vector> coefs; 208 | string line, directionfile; 209 | int line_idx = 0; 210 | 211 | // Open file for reading 212 | if (direction==1) { 213 | // Forward pipeline 214 | directionfile = string("raw2jpg_coefs.txt"); 215 | } else { 216 | // Backward pipeline 217 | directionfile = string("jpg2raw_coefs.txt"); 218 | } 219 | ifstream file(cam_model_path+directionfile); 220 | 221 | // Read a line at a time 222 | while(getline(file, line)) 223 | { 224 | vector lineData, temp; 225 | stringstream lineStream(line); 226 | float value; 227 | // Read one value at a time from the line 228 | while(lineStream >> value) 229 | { 230 | lineData.push_back(value); 231 | } 232 | if (line_idx>=(num_cntrl_pts+1) && line_idx<=(num_cntrl_pts+4)) { 233 | for (int i=0; i<3; i++) { 234 | temp.push_back(lineData[i]); 235 | } 236 | coefs.push_back(temp); 237 | } 238 | line_idx = line_idx + 1; 239 | } 240 | 241 | return coefs; 242 | 243 | } 244 | 245 | // Get reverse tone mapping 246 | vector> get_rev_tone(char* cam_model_path) { 247 | 248 | vector> rev_tone; 249 | string line; 250 | int line_idx = 0; 251 | 252 | // Open file for reading 253 | ifstream file(cam_model_path+string("jpg2raw_respFcns.txt")); 254 | 255 | // Read a line at a time 256 | while(getline(file, line)) 257 | { 258 | vector lineData, temp; 259 | stringstream lineStream(line); 260 | float value; 261 | // Read one value at a time from the line 262 | while(lineStream >> value) 263 | { 264 | lineData.push_back(value); 265 | } 266 | if (line_idx>=1 && line_idx<=256) { 267 | for (int i=0; i<3; i++) { 268 | temp.push_back(lineData[i]); 269 | } 270 | rev_tone.push_back(temp); 271 | } 272 | line_idx = line_idx + 1; 273 | } 274 | 275 | return rev_tone; 276 | 277 | } 278 | 279 | 280 | -------------------------------------------------------------------------------- /src/Halide/LoadCamModel.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | // Get color space transform 11 | vector> get_Ts(char* cam_model_path); 12 | 13 | // Get white balance transform 14 | vector> get_Tw(char* cam_model_path, int wb_index); 15 | 16 | // Get combined transforms for checking 17 | vector> get_TsTw(char* cam_model_path, int wb_index); 18 | 19 | // Get control points 20 | vector> get_ctrl_pts(char* cam_model_path, int num_cntrl_pts, bool direction); 21 | 22 | // Get weights 23 | vector> get_weights(char* cam_model_path, int num_cntrl_pts, bool direction); 24 | 25 | // Get coeficients 26 | vector> get_coefs(char* cam_model_path, int num_cntrl_pts, bool direction); 27 | 28 | // Get reverse tone mapping 29 | vector> get_rev_tone(char* cam_model_path); 30 | -------------------------------------------------------------------------------- /src/Halide/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile test 3 | 4 | all: 5 | #g++ lesson_12_using_the_gpu.cpp -g -I ~/packages/Halide/include/ -I ~/packages/Halide/tools -L ~/packages/Halide/bin -lHalide `libpng-config --cflags --ldflags` -lpthread -ldl -lraw -lOpenCL -lrt -lm -o Lesson12 -std=c++11 6 | g++ ImgPipe_Halide.cpp LoadCamModel.cpp MatrixOps.cpp -g -I ~/packages/Halide/include/ -I ~/packages/Halide/tools -I ~/packages/Halide/tools -L ~/packages/Halide/bin -lHalide `libpng-config --cflags --ldflags` -lpthread -ldl -lm -o ImgPipe -std=c++11 7 | -------------------------------------------------------------------------------- /src/Halide/MatrixOps.cpp: -------------------------------------------------------------------------------- 1 | #include "MatrixOps.h" 2 | 3 | using namespace std; 4 | 5 | // Transpose a matrix 6 | vector> transpose_mat (vector> inmat) { 7 | 8 | // Get size of input 9 | int in_width = inmat[0].size(); 10 | int in_height = inmat.size(); 11 | 12 | // Define vectors 13 | vector> outmat (in_width, vector(in_height)); 14 | 15 | // Transpose the matrix 16 | for (int i=0; i> dot_matmat (vector> a, vector> b) { 28 | 29 | int width = b[0].size(); 30 | int height = a.size(); 31 | 32 | int a_inner_dim = a[0].size(); 33 | int b_inner_dim = b.size(); 34 | 35 | // Define output size 36 | vector> result (height, vector(width)); 37 | 38 | // Take the transpose of b for more convenient multiplication 39 | vector> b_trans = transpose_mat(b); 40 | 41 | // Verify that the inner dimensions are the same 42 | if (a_inner_dim != b_inner_dim) 43 | throw invalid_argument("Attempt to dot product matrices with different inner dimensions"); 44 | 45 | // Multiply the matrices 46 | for (int i=0; i dot_vecmat (vector a, vector> b) { 58 | 59 | } 60 | 61 | // Vector Vector Dot Product 62 | float dot_vecvec (vector a, vector b) { 63 | 64 | float result = 0; 65 | int size_a = a.size(); 66 | int size_b = b.size(); 67 | 68 | // Verify that both vectors are of the same size 69 | if (size_a != size_b) 70 | throw invalid_argument("Attempt to dot product vectors of different size"); 71 | 72 | // Multiply the vectors 73 | for (int i=0; i> inv_3x3mat (vector> inmat) { 83 | vector> result; 84 | result = inmat; 85 | 86 | float det = inmat[0][0] * (inmat[1][1] * inmat[2][2] - inmat[2][1] * inmat[1][2]) - 87 | inmat[0][1] * (inmat[1][0] * inmat[2][2] - inmat[1][2] * inmat[2][0]) + 88 | inmat[0][2] * (inmat[1][0] * inmat[2][1] - inmat[1][1] * inmat[2][0]); 89 | 90 | float invdet = 1/det; 91 | 92 | result[0][0] = (inmat[1][1] * inmat[2][2] - inmat[2][1] * inmat[1][2]) * invdet; 93 | result[0][1] = (inmat[0][2] * inmat[2][1] - inmat[0][1] * inmat[2][2]) * invdet; 94 | result[0][2] = (inmat[0][1] * inmat[1][2] - inmat[0][2] * inmat[1][1]) * invdet; 95 | result[1][0] = (inmat[1][2] * inmat[2][0] - inmat[1][0] * inmat[2][2]) * invdet; 96 | result[1][1] = (inmat[0][0] * inmat[2][2] - inmat[0][2] * inmat[2][0]) * invdet; 97 | result[1][2] = (inmat[1][0] * inmat[0][2] - inmat[0][0] * inmat[1][2]) * invdet; 98 | result[2][0] = (inmat[1][0] * inmat[2][1] - inmat[2][0] * inmat[1][1]) * invdet; 99 | result[2][1] = (inmat[2][0] * inmat[0][1] - inmat[0][0] * inmat[2][1]) * invdet; 100 | result[2][2] = (inmat[0][0] * inmat[1][1] - inmat[1][0] * inmat[0][1]) * invdet; 101 | 102 | return result; 103 | } 104 | 105 | // Display matrix 106 | void disp_mat (vector> mat) { 107 | 108 | int height = mat.size(); 109 | int width = mat[0].size(); 110 | 111 | for (int i=0; i 2 | #include 3 | 4 | using namespace std; 5 | 6 | // Transpose a matrix 7 | vector> transpose_mat (vector> inmat); 8 | 9 | // Matrix Matrix Dot Product 10 | vector> dot_matmat (vector> a, vector> b); 11 | 12 | // Vector Matrix Dot Product 13 | vector dot_vecmat (vector a, vector> b); 14 | 15 | // Vector Vector Dot Product 16 | float dot_vecvec (vector a, vector b); 17 | 18 | // Three by three matrix inversion 19 | vector> inv_3x3mat (vector> inmat); 20 | 21 | // Visualize matrix 22 | void disp_mat (vector> mat); 23 | -------------------------------------------------------------------------------- /src/Halide/README.txt: -------------------------------------------------------------------------------- 1 | 2 | ##################################################################### 3 | # Halide implementation of the forward and backward pipeline 4 | ##################################################################### 5 | 6 | ##################################################################### 7 | # How to use 8 | ##################################################################### 9 | 10 | 1) Install Halide in ~/packages/Halide/. Alternatively, install in 11 | a directory of your choice and update the makefile. 12 | Halide docs: http://halide-lang.org/index.html#gettingstarted 13 | 14 | 2) If you would like to run the forward version of the pipeline 15 | on a new image, go to src/scripts and run the RawPreprocessor 16 | on the raw image to demosaic it and write it to a png. 17 | 18 | 3) Update ImgPipeConfig.h to account for any changes you would like 19 | > vim ImgPipeConfig.h 20 | 21 | 4) In this directory, run make 22 | > make 23 | 24 | 5) Then execute the code with the ImgPipe command 25 | > ./ImgPipe 26 | 27 | 6) Observe your output file(s) in this directory 28 | 29 | ##################################################################### 30 | # Directory contents 31 | ##################################################################### 32 | 33 | * ImgPipeConfig.h 34 | Config file for the image pipeline. Contains information on the 35 | location of the camera model and the image to test. 36 | 37 | * ImgPipe_Halide.cpp 38 | The primary file, contains all Halide code for the pipeline 39 | 40 | * LoadCamModel.cpp 41 | Loads all information from the camera model 42 | 43 | * MatrixOps.cpp 44 | A few linear algebra functions. Implementing them here prevents 45 | the need to install YAL (Yet Another Library) 46 | 47 | * clock.h 48 | Helper file for determining computation speed 49 | 50 | ##################################################################### 51 | # Additional notes 52 | ##################################################################### 53 | 54 | A few changes may be needed to use the Makefile on non Linux 55 | distributions 56 | -------------------------------------------------------------------------------- /src/Halide/clock.h: -------------------------------------------------------------------------------- 1 | // A current_time function for use in the tests. Returns time in 2 | // milliseconds. 3 | 4 | #ifdef _WIN32 5 | #include 6 | double current_time() { 7 | LARGE_INTEGER freq, t; 8 | QueryPerformanceCounter(&t); 9 | QueryPerformanceFrequency(&freq); 10 | return (t.QuadPart * 1000.0) / freq.QuadPart; 11 | } 12 | // Gross, these come from Windows.h 13 | #undef max 14 | #undef min 15 | #else 16 | #include 17 | double current_time() { 18 | static bool first_call = true; 19 | static timeval reference_time; 20 | if (first_call) { 21 | first_call = false; 22 | gettimeofday(&reference_time, NULL); 23 | return 0.0; 24 | } else { 25 | timeval t; 26 | gettimeofday(&t, NULL); 27 | return ((t.tv_sec - reference_time.tv_sec)*1000.0 + 28 | (t.tv_usec - reference_time.tv_usec)/1000.0); 29 | } 30 | } 31 | #endif 32 | -------------------------------------------------------------------------------- /src/Matlab/ImgPipe_Matlab.m: -------------------------------------------------------------------------------- 1 | %============================================================== 2 | % Image Processing Pipeline 3 | % 4 | % This is a Matlab implementation of a pre-learned image 5 | % processing model. A description of the model can be found in 6 | % "A New In-Camera Imaging Model for Color Computer Vision 7 | % and its Application" by Seon Joo Kim, Hai Ting Lin, 8 | % Michael Brown, et al. Code for learning a new model can 9 | % be found at the original project page. This particular 10 | % implementation was written by Mark Buckler. 11 | % 12 | % Original Project Page: 13 | % http://www.comp.nus.edu.sg/~brown/radiometric_calibration/ 14 | % 15 | % Model Format Readme: 16 | % http://www.comp.nus.edu.sg/~brown/radiometric_calibration/datasets/Model_param/readme.pdf 17 | % 18 | %============================================================== 19 | 20 | function ImgPipe_Matlab 21 | % Model directory 22 | model_dir = '../../camera_models/NikonD7000/'; 23 | 24 | % White balance index (select from the transform file) 25 | % First white balance in file has wb_index of 1 26 | % For more information see the model readme 27 | wb_index = 6; 28 | 29 | % Image directory 30 | image_dir = '../../imgs/NikonD7000FL/'; 31 | 32 | % Results directory 33 | results_dir = 'pipe_results/'; 34 | 35 | % Raw image 36 | raw_image_name = 'DSC_0916.NEF.raw_1C.tiff'; 37 | 38 | % Jpg image 39 | jpg_image_name = 'DSC_0916.JPG'; 40 | 41 | % Create directories for results 42 | mkdir(pwd, results_dir); 43 | mkdir(pwd, strcat(results_dir,'forward_images/')); 44 | mkdir(pwd, strcat(results_dir,'backward_images/')); 45 | 46 | % Patch start locations 47 | % [xstart,ystart] 48 | % 49 | % NOTE: Must align patch start in raw file with the demosiac 50 | % pattern start. Otherwise colors will be switched in the 51 | % final result. 52 | patchstarts = [ ... 53 | [551, 2751]; ... % 1 54 | [1001, 2751]; ... % 2 55 | [1501, 2751]; ... % 3 56 | [2001, 2751]; ... % 4 57 | [551, 2251]; ... % 5 58 | [1001, 2251]; ... % 6 59 | [1501, 2251]; ... % 7 60 | [2001, 2251]; ... % 8 61 | [551, 1751]; ... % 9 62 | [1001, 1751]; ... % 10 63 | [1501, 1751]; ... % 11 64 | [2001, 1751]; ... % 12 65 | ]; 66 | 67 | % Number of patch tests to run 68 | patchnum = 12; 69 | 70 | % Define patch size (patch width and height in pixels 71 | patchsize = 10; 72 | 73 | % Initialize results 74 | forward_results = zeros(patchnum,3,3); 75 | backward_results = zeros(patchnum,3,3); 76 | 77 | % Process patches 78 | for i=1:patchnum 79 | 80 | % Run the forward model on the patch 81 | [demosaiced, transformed, gamutmapped, tonemapped, forward_ref] = ... 82 | ForwardPipe(model_dir, image_dir, results_dir, wb_index, ... 83 | raw_image_name, jpg_image_name, ... 84 | patchstarts(i,2), patchstarts(i,1), patchsize, i); 85 | 86 | % Compare the pipeline output to the reference 87 | [refavg, resultavg, error] = ... 88 | patch_compare(tonemapped, forward_ref); 89 | forward_results(i,1,:) = resultavg; 90 | forward_results(i,2,:) = refavg; 91 | forward_results(i,3,:) = error; 92 | 93 | % Run the backward model on the patch 94 | [revtonemapped, revgamutmapped, revtransformed, remosaiced, backward_ref] = ... 95 | BackwardPipe(model_dir, image_dir, results_dir, wb_index, ... 96 | jpg_image_name, raw_image_name, ... 97 | patchstarts(i,2), patchstarts(i,1), patchsize, i); 98 | 99 | % Compare the pipeline output to the reference 100 | [refavg, resultavg, error] = ... 101 | patch_compare(remosaiced, backward_ref); 102 | backward_results(i,1,:) = resultavg; 103 | backward_results(i,2,:) = refavg; 104 | backward_results(i,3,:) = error; 105 | 106 | end 107 | 108 | write_results(forward_results, patchnum, ... 109 | strcat(results_dir,'forward_results.txt')); 110 | write_results(backward_results, patchnum, ... 111 | strcat(results_dir,'backward_results.txt')); 112 | 113 | disp(strcat('Avg % color channel error for forward: ', ... 114 | num2str(mean(mean(abs(forward_results(:,3,:))))))); 115 | disp(strcat('Avg % color channel error for backward: ', ... 116 | num2str(mean(mean(abs(backward_results(:,3,:))))))); 117 | 118 | disp(strcat('Max % color channel error for forward: ', ... 119 | num2str(max(max(abs(forward_results(:,3,:))))))); 120 | disp(strcat('Max % color channel error for backward: ', ... 121 | num2str(max(max(abs(backward_results(:,3,:))))))); 122 | 123 | disp('See results folder for error per patch and per color channel'); 124 | 125 | end 126 | 127 | 128 | function [demosaiced, transformed, gamutmapped, tonemapped, ref_image] = ... 129 | ForwardPipe(model_dir, image_dir, results_dir, wb_index, ... 130 | in_image_name, ref_image_name, ystart, xstart, patchsize, patchid) 131 | 132 | % Establish patch 133 | xend = xstart + patchsize - 1; 134 | yend = ystart + patchsize - 1; 135 | 136 | %============================================================== 137 | % Import Forward Model Data 138 | % 139 | % Note: This assumes a camera model folder with a single 140 | % camera setting and transform. This is not the case for 141 | % every folder, but it is for the Nikon D40 on the Normal 142 | % setting and with Fl(L14)/florescent color. 143 | 144 | % Model file reading 145 | transforms_file = dlmread( ... 146 | strcat(model_dir,'raw2jpg_transform.txt')); 147 | ctrl_points_file = dlmread( ... 148 | strcat(model_dir,'raw2jpg_ctrlPoints.txt')); 149 | coeficients_file = dlmread( ... 150 | strcat(model_dir,'raw2jpg_coefs.txt')); 151 | resp_funct_file = dlmread( ... 152 | strcat(model_dir,'raw2jpg_respFcns.txt')); 153 | 154 | % Color space transform 155 | Ts = transforms_file(2:4,:); 156 | 157 | % Calculate base for the white balance transform selected 158 | % For more details see the camera model readme 159 | wb_base = 6 + 5*(wb_index-1); 160 | 161 | % White balance transform 162 | Tw = diag(transforms_file(wb_base+3,:)); 163 | 164 | % Combined transforms 165 | TsTw = Ts*Tw; 166 | TsTw_file = transforms_file(wb_base:wb_base+2,:); 167 | 168 | % Perform quick check to determine equivalence with provided model 169 | % Round to nearest 4 decimal representation for check 170 | TsTw_4dec = round(TsTw*10000)/10000; 171 | TsTw_file_4dec = round(TsTw_file*10000)/10000; 172 | assert( isequal( TsTw_4dec, TsTw_file_4dec), ... 173 | 'Transform multiplication not equal to result found in model file, or import failed' ) 174 | 175 | % Gamut mapping: Control points 176 | ctrl_points = ctrl_points_file(2:end,:); 177 | 178 | % Gamut mapping: Weights 179 | weights = coeficients_file(2:(size(coeficients_file,1)-4),:); 180 | 181 | % Gamut mapping: c 182 | c = coeficients_file((size(coeficients_file,1)-3):end,:); 183 | 184 | % Tone mapping (reverse function is what is contained within model 185 | % file) 186 | frev = resp_funct_file(2:end,:); 187 | 188 | %============================================================== 189 | % Import Raw Image Data 190 | 191 | % NOTE: Can use RAW2TIFF.cpp to convert raw to tiff. This isn't 192 | % automatically called by this script yet, but could be. 193 | 194 | in_image = imread(strcat(image_dir,in_image_name)); 195 | 196 | %============================================================== 197 | % Import Reference image 198 | 199 | ref_image = imread(strcat(image_dir,ref_image_name)); 200 | 201 | % Downsize to match patch size 202 | ref_image = ref_image(ystart:yend,xstart:xend,:); 203 | 204 | %============================================================== 205 | % Forward pipeline function 206 | 207 | % Convert to uint16 representation for demosaicing 208 | in_image_unit16 = im2uint16(in_image); 209 | 210 | % Demosaic image 211 | demosaiced = im2uint8(demosaic(in_image_unit16,'rggb'));%gbrg %rggb 212 | 213 | % Convert to double precision for transforming and gamut mapping 214 | image_float = im2double(demosaiced); 215 | 216 | % Downsize image to patch size 217 | demosaiced = demosaiced(ystart:yend,xstart:xend,:); 218 | image_float = image_float(ystart:yend,xstart:xend,:); 219 | 220 | % Pre-allocate memory 221 | height = size(image_float,1); 222 | width = size(image_float,2); 223 | transformed = zeros(height,width,3); 224 | gamutmapped = zeros(height,width,3); 225 | tonemapped = zeros(height,width,3); 226 | 227 | 228 | for y = 1:height 229 | for x = 1:width 230 | 231 | % transformed = RAWdemosaiced * Ts * Tw 232 | transformed(y,x,:) = transpose(squeeze(image_float(y,x,:))) ... 233 | * transpose(TsTw); 234 | 235 | % gamut mapping 236 | gamutmapped(y,x,:) = RBF(squeeze(transformed(y,x,:)), ... 237 | ctrl_points, weights, c); 238 | 239 | % tone mapping 240 | tonemapped(y,x,:) = tonemap(im2uint8(squeeze(gamutmapped(y,x,:))), frev); 241 | 242 | end 243 | % Let user know how far along we are 244 | disp((y/size(image_float,1))*100) 245 | end 246 | 247 | %============================================================== 248 | % Export Image(s) 249 | 250 | ref_image = im2uint8(ref_image); 251 | image_float = im2uint8(image_float); 252 | transformed = im2uint8(transformed); 253 | gamutmapped = im2uint8(gamutmapped); 254 | tonemapped = im2uint8(tonemapped); 255 | 256 | imwrite(ref_image, strcat(results_dir, ... 257 | 'forward_images/', in_image_name, ... 258 | '.p',int2str(patchid),'.forward_reference.tif')); 259 | imwrite(tonemapped, strcat(results_dir, ... 260 | 'forward_images/', in_image_name, ... 261 | '.p',int2str(patchid),'.forward_result.tif')); 262 | 263 | 264 | end 265 | 266 | function [revtonemapped, revgamutmapped, revtransformed, remosaiced, ref_image_colored] = ... 267 | BackwardPipe(model_dir, image_dir, results_dir, wb_index, ... 268 | in_image_name, ref_image_name, ystart, xstart, patchsize, patchid) 269 | 270 | % Establish patch 271 | xend = xstart + patchsize - 1; 272 | yend = ystart + patchsize - 1; 273 | 274 | %============================================================== 275 | % Import Backward Model Data 276 | % 277 | % Note: This assumes a camera model folder with a single 278 | % camera setting and transform. This is not the case for 279 | % every folder, but it is for the Nikon D40 on the Normal 280 | % setting and with Fl(L14)/florescent color. 281 | 282 | % Model file reading 283 | % Model file reading 284 | transforms_file = dlmread( ... 285 | strcat(model_dir,'jpg2raw_transform.txt')); 286 | ctrl_points_file = dlmread( ... 287 | strcat(model_dir,'jpg2raw_ctrlPoints.txt')); 288 | coeficients_file = dlmread( ... 289 | strcat(model_dir,'jpg2raw_coefs.txt')); 290 | resp_funct_file = dlmread( ... 291 | strcat(model_dir,'jpg2raw_respFcns.txt')); 292 | 293 | % Color space transform 294 | Ts = transforms_file(2:4,:); 295 | 296 | % Calculate base for the white balance transform selected 297 | % For more details see the camera model readme 298 | wb_base = 6 + 5*(wb_index-1); 299 | 300 | % White balance transform 301 | Tw = diag(transforms_file(wb_base+3,:)); 302 | 303 | % Combined transforms 304 | TsTw = Ts*Tw; 305 | TsTw_file = transforms_file(wb_base:wb_base+2,:); 306 | 307 | % Perform quick check to determine equivalence with provided model 308 | % Round to nearest 4 decimal representation for check 309 | TsTw_4dec = round(TsTw*10000)/10000; 310 | TsTw_file_4dec = round(TsTw_file*10000)/10000; 311 | assert( isequal( TsTw_4dec, TsTw_file_4dec), ... 312 | 'Transform multiplication not equal to result found in model file, or import failed' ) 313 | 314 | % Gamut mapping: Control points 315 | ctrl_points = ctrl_points_file(2:end,:); 316 | 317 | % Gamut mapping: Weights 318 | weights = coeficients_file(2:(size(coeficients_file,1)-4),:); 319 | 320 | % Gamut mapping: c 321 | c = coeficients_file((size(coeficients_file,1)-3):end,:); 322 | 323 | % Tone mapping (reverse function is what is contained within model 324 | % file) 325 | frev = resp_funct_file(2:end,:); 326 | 327 | %============================================================== 328 | % Import Image Data 329 | 330 | in_image = imread(strcat(image_dir,in_image_name)); 331 | ref_image = imread(strcat(image_dir,ref_image_name)); 332 | 333 | % Convert the input image to double represenation 334 | ref_image = im2double(ref_image); 335 | 336 | %============================================================== 337 | % Backward pipeline function 338 | 339 | % Convert to double precision for processing 340 | image_float = im2double(in_image); 341 | 342 | % Extract patches 343 | image_float = image_float(ystart:yend,xstart:xend,:); 344 | ref_image = ref_image (ystart:yend,xstart:xend); 345 | 346 | % Pre-allocate memory 347 | height = size(image_float,1); 348 | width = size(image_float,2); 349 | revtransformed = zeros(height,width,3); 350 | revtonemapped = zeros(height,width,3); 351 | revgamutmapped = zeros(height,width,3); 352 | remosaiced = zeros(height,width,3); 353 | ref_image_colored = zeros(height,width,3); 354 | 355 | for y = 1:height 356 | for x = 1:width 357 | 358 | % Reverse tone mapping 359 | revtonemapped(y,x,:) = revtonemap(squeeze(image_float(y,x,:)), frev); 360 | 361 | % Reverse gamut mapping 362 | revgamutmapped(y,x,:) = RBF(squeeze(revtonemapped(y,x,:)), ... 363 | ctrl_points, weights, c); 364 | 365 | % Reverse color mapping and white balancing 366 | % RAWdemosaiced = transformed * inv(TsTw) = transformed / TsTw 367 | revtransformed(y,x,:) = transpose(squeeze(revgamutmapped(y,x,:))) ... 368 | * inv(transpose(TsTw)); 369 | 370 | % Re-mosaicing 371 | % Note: This is not currently parameterizable, assumes rggb 372 | yodd = mod(y,2); 373 | xodd = mod(x,2); 374 | % If a red pixel 375 | if yodd && xodd 376 | remosaiced(y,x,:) = [revtransformed(y,x,1), 0, 0]; 377 | % If a green pixel 378 | elseif xor(yodd,xodd) 379 | remosaiced(y,x,:) = [0, revtransformed(y,x,2), 0]; 380 | % If a blue pixel 381 | elseif ~yodd && ~xodd 382 | remosaiced(y,x,:) = [0, 0, revtransformed(y,x,3)]; 383 | end 384 | 385 | %====================================================== 386 | % Reorganize reference image 387 | % Note: This is not currently parameterizable, assumes rggb 388 | % If a red pixel 389 | if yodd && xodd 390 | ref_image_colored(y,x,:) = [ref_image(y,x), 0, 0]; 391 | % If a green pixel 392 | elseif xor(yodd,xodd) 393 | ref_image_colored(y,x,:) = [0, ref_image(y,x), 0]; 394 | % If a blue pixel 395 | elseif ~yodd && ~xodd 396 | ref_image_colored(y,x,:) = [0, 0, ref_image(y,x)]; 397 | end 398 | 399 | end 400 | % Let user know how far along we are 401 | disp((y/size(image_float,1))*100) 402 | end 403 | 404 | 405 | %============================================================== 406 | % Export Image(s) 407 | 408 | ref_image = im2uint8(ref_image); 409 | ref_image_colored = im2uint8(ref_image_colored); 410 | revtransformed = im2uint8(revtransformed); 411 | revtonemapped = im2uint8(revtonemapped); 412 | revgamutmapped = im2uint8(revgamutmapped); 413 | remosaiced = im2uint8(remosaiced); 414 | 415 | imwrite(ref_image, strcat(results_dir, ... 416 | 'backward_images/', in_image_name, ... 417 | '.p',int2str(patchid),'.back_ref.tif')); 418 | imwrite(ref_image_colored, strcat(results_dir, ... 419 | 'backward_images/', in_image_name, ... 420 | '.p',int2str(patchid),'.back_ref_colored.tif')); 421 | imwrite(remosaiced, strcat(results_dir, ... 422 | 'backward_images/', in_image_name, ... 423 | '.p',int2str(patchid),'.back_result.tif')); 424 | 425 | 426 | end 427 | 428 | 429 | % Radial basis function for forward and reverse gamut mapping 430 | function out = RBF (in, ctrl_points, weights, c) 431 | 432 | out = zeros(3,1); 433 | 434 | % Weighted control points 435 | for idx = 1:size(ctrl_points,1) 436 | dist = norm(transpose(in) - ctrl_points(idx,:)); 437 | for color = 1:3 438 | out(color) = out(color) + weights(idx,color) * dist; 439 | end 440 | end 441 | 442 | % Biases 443 | for color = 1:3 444 | out(color) = out(color) + c(1,color); 445 | out(color) = out(color) + (c(2,color) * in(1)); 446 | out(color) = out(color) + (c(3,color) * in(2)); 447 | out(color) = out(color) + (c(4,color) * in(3)); 448 | end 449 | 450 | end 451 | 452 | % Forward mapping function 453 | function out = tonemap (in, revf) 454 | 455 | out = zeros(3,1); 456 | 457 | for color = 1:3 % 1-R, 2-G, 3-B 458 | % Find index of value which is closest to the input 459 | [~,idx] = min(abs(revf(:,color)-im2double(in(color)))); 460 | 461 | % If index is zero, bump up to 1 to prevent 0 indexing in Matlab 462 | if idx == 0 463 | idx = 1; 464 | end 465 | 466 | % Convert the index to float representation of image value 467 | out(color) = idx/256; 468 | end 469 | 470 | end 471 | 472 | % Reverse tone mapping function 473 | function out = revtonemap (in, revf) 474 | 475 | out = zeros(3,1); 476 | 477 | for color = 1:3 % 1-R, 2-G, 3-B 478 | % Convert the input to an integer between 1 and 256 479 | idx = round(in(color)*256); 480 | 481 | % If index is zero, bump up to 1 to prevent 0 indexing in Matlab 482 | if idx == 0 483 | idx = 1; 484 | end 485 | 486 | % Index the reverse tone mapping function 487 | out(color) = revf(idx,color); 488 | end 489 | 490 | end 491 | 492 | % Patch color analysis and comparison function 493 | function [refavg, resultavg, error] = patch_compare(resultpatch, referencepatch) 494 | 495 | refavg = zeros(3,1); 496 | resultavg = zeros(3,1); 497 | error = zeros(3,1); 498 | 499 | for color = 1:3 % 1-R, 2-G, 3-B 500 | % Take two dimensional pixel averages 501 | refavg(color) = mean(mean(referencepatch(:,:,color))); 502 | resultavg(color) = mean(mean(resultpatch(:,:,color))); 503 | % Compute error 504 | diff = resultavg(color)-refavg(color); 505 | error(color) = (diff/256.0)*100; 506 | end 507 | 508 | end 509 | 510 | % Write the pipeline data results to an output file 511 | function write_results(results, patchnum, file_name) 512 | 513 | outfileID = fopen(file_name, 'w'); 514 | 515 | % Display results 516 | fprintf(outfileID, 'res(red), res(green), res(blue)\n'); 517 | fprintf(outfileID, 'ref(red), ref(green), ref(blue)\n'); 518 | fprintf(outfileID, 'err(red), err(green), err(blue)\n'); 519 | fprintf(outfileID, '\n'); 520 | for i=1:patchnum 521 | fprintf(outfileID, 'Patch %d: \n', i); 522 | % Print results 523 | fprintf(outfileID, '%4.2f, %4.2f, %4.2f \n', ... 524 | results(i,1,1), results(i,1,2), results(i,1,3)); 525 | % Print reference 526 | fprintf(outfileID, '%4.2f, %4.2f, %4.2f \n', ... 527 | results(i,2,1), results(i,2,2), results(i,2,3)); 528 | % Print error 529 | fprintf(outfileID, '%4.2f, %4.2f, %4.2f \n', ... 530 | results(i,3,1), results(i,3,2), results(i,3,3)); 531 | fprintf(outfileID, '\n'); 532 | end 533 | 534 | end -------------------------------------------------------------------------------- /src/Matlab/README.txt: -------------------------------------------------------------------------------- 1 | 2 | ##################################################################### 3 | # Matlab implementation of the forward and backward pipeline 4 | ##################################################################### 5 | 6 | ##################################################################### 7 | # How to use 8 | ##################################################################### 9 | 10 | Directions below are for using this pipeline with new images, 11 | If you are only interested in running with the provided images 12 | and model, then all you need to do is run ImgPipe_Matlab.m. 13 | 14 | 1) Install Matlab 15 | Matlab docs: http://www.mathworks.com/help/install/ug/install-mathworks-software.html 16 | 17 | 2) Run the raw preprocessor in src/scripts. Note that matlab 18 | wants the scaled but not demosaiced version. This will have 19 | an extension of .raw_1C.tiff, not .demos_3C.png. 20 | 21 | 3) Edit any points within the matlab code that you would like 22 | to change. This might include: 23 | * Where your processed images are 24 | * Where your camera model is stored 25 | * The patches to test in your image. Ensure that your xstart and 26 | ystart align with the start of the bayer mosaic pattern. 27 | * The raw image mosaic pattern. Not all cameras have the same pixel 28 | alignment. Ensure that the forward and backward pipelines have 29 | the right pattern. 30 | 31 | 4) Run ImgPipe_Matlab.m 32 | 33 | 5) Observe your output in src/Matlab/pipe_results/ 34 | 35 | ##################################################################### 36 | # Pipeline Results Folder Contents 37 | ##################################################################### 38 | 39 | After running the pipeline you will see a new folder created in this 40 | directory called pipe_results. In this directory you will have folders 41 | for forward results and images as well as backward results and images. 42 | The result text files contain values and error metrics for each of 43 | the patches which have been tested. The image folders contain the 44 | image outputs of each of the respective pipelines. 45 | -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/README.txt: -------------------------------------------------------------------------------- 1 | These sample results are of the NikonD7000 model with 2 | the normal setting and Fl (flourescent) transform. The 3 | color map image used is the DSC_0916.NEF.raw_1C.tiff and 4 | DSC_0916.JPG. 5 | -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p1.back_ref.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p1.back_ref.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p1.back_ref_colored.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p1.back_ref_colored.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p1.back_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p1.back_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p2.back_ref.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p2.back_ref.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p2.back_ref_colored.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p2.back_ref_colored.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p2.back_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p2.back_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p3.back_ref.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p3.back_ref.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p3.back_ref_colored.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p3.back_ref_colored.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p3.back_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p3.back_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p4.back_ref.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p4.back_ref.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p4.back_ref_colored.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p4.back_ref_colored.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p4.back_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p4.back_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p5.back_ref.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p5.back_ref.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p5.back_ref_colored.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p5.back_ref_colored.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p5.back_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p5.back_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p6.back_ref.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p6.back_ref.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p6.back_ref_colored.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p6.back_ref_colored.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p6.back_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p6.back_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p7.back_ref.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p7.back_ref.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p7.back_ref_colored.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p7.back_ref_colored.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p7.back_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p7.back_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p8.back_ref.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p8.back_ref.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p8.back_ref_colored.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p8.back_ref_colored.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p8.back_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/backward_images/DSC_0916.JPG.p8.back_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/backward_results.txt: -------------------------------------------------------------------------------- 1 | res(red), res(green), res(blue) 2 | ref(red), ref(green), ref(blue) 3 | err(red), err(green), err(blue) 4 | 5 | Patch 1: 6 | 3.00, 6.31, 1.04 7 | 3.03, 6.45, 1.15 8 | -0.99, -2.17, -9.57 9 | 10 | Patch 2: 11 | 13.50, 18.52, 1.50 12 | 11.40, 15.55, 1.27 13 | 18.42, 19.10, 18.11 14 | 15 | Patch 3: 16 | 1.02, 5.28, 3.38 17 | 1.13, 5.39, 3.42 18 | -9.73, -2.04, -1.17 19 | 20 | Patch 4: 21 | 18.94, 60.87, 13.91 22 | 18.91, 60.89, 13.94 23 | 0.16, -0.03, -0.22 24 | 25 | Patch 5: 26 | 10.28, 20.56, 4.06 27 | 10.15, 20.40, 4.04 28 | 1.28, 0.78, 0.50 29 | 30 | Patch 6: 31 | 2.25, 9.49, 5.09 32 | 2.27, 9.54, 5.20 33 | -0.88, -0.52, -2.12 34 | 35 | Patch 7: 36 | 3.01, 19.18, 2.25 37 | 3.13, 19.23, 2.34 38 | -3.83, -0.26, -3.85 39 | 40 | Patch 8: 41 | 12.64, 41.50, 9.59 42 | 12.75, 41.55, 9.62 43 | -0.86, -0.12, -0.31 44 | 45 | -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p1.forward_reference.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p1.forward_reference.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p1.forward_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p1.forward_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p2.forward_reference.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p2.forward_reference.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p2.forward_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p2.forward_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p3.forward_reference.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p3.forward_reference.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p3.forward_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p3.forward_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p4.forward_reference.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p4.forward_reference.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p4.forward_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p4.forward_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p5.forward_reference.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p5.forward_reference.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p5.forward_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p5.forward_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p6.forward_reference.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p6.forward_reference.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p6.forward_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p6.forward_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p7.forward_reference.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p7.forward_reference.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p7.forward_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p7.forward_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p8.forward_reference.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p8.forward_reference.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p8.forward_result.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuckler/ReversiblePipeline/64363b5d1ff7dcabe8cebcdd18e3503fdb9617ca/src/Matlab/sample_pipe_results/forward_images/DSC_0916.NEF.raw_1C.tiff.p8.forward_result.tif -------------------------------------------------------------------------------- /src/Matlab/sample_pipe_results/forward_results.txt: -------------------------------------------------------------------------------- 1 | res(red), res(green), res(blue) 2 | ref(red), ref(green), ref(blue) 3 | err(red), err(green), err(blue) 4 | 5 | Patch 1: 6 | 140.97, 87.60, 58.11 7 | 141.31, 84.55, 58.97 8 | -0.24, 3.61, -1.46 9 | 10 | Patch 2: 11 | 253.13, 132.84, 50.27 12 | 255.00, 134.13, 57.04 13 | -0.73, -0.96, -11.87 14 | 15 | Patch 3: 16 | 53.74, 53.28, 172.61 17 | 53.06, 51.84, 171.46 18 | 1.28, 2.78, 0.67 19 | 20 | Patch 4: 21 | 241.61, 228.22, 220.54 22 | 241.69, 228.31, 220.79 23 | -0.03, -0.04, -0.11 24 | 25 | Patch 5: 26 | 230.60, 154.32, 133.48 27 | 231.20, 154.16, 135.54 28 | -0.26, 0.10, -1.52 29 | 30 | Patch 6: 31 | 102.85, 95.05, 209.00 32 | 103.75, 95.45, 207.59 33 | -0.87, -0.42, 0.68 34 | 35 | Patch 7: 36 | 96.37, 180.44, 74.06 37 | 94.96, 181.24, 71.90 38 | 1.48, -0.44, 3.00 39 | 40 | Patch 8: 41 | 221.61, 204.14, 196.50 42 | 221.42, 203.98, 196.38 43 | 0.09, 0.08, 0.06 44 | 45 | -------------------------------------------------------------------------------- /src/OpenCV/compare_imgs.py: -------------------------------------------------------------------------------- 1 | # import the necessary packages 2 | 3 | #from skimage.measure import structural_similarity as ssim 4 | import matplotlib.pyplot as plt 5 | import numpy as np 6 | import cv2 7 | 8 | def get_mse(imageA, imageB): 9 | # the 'Mean Squared Error' between the two images is the 10 | # sum of the squared difference between the two images; 11 | # NOTE: the two images must have the same dimension 12 | err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2) 13 | err /= float(imageA.shape[0] * imageA.shape[1] * imageA.shape[2]) 14 | 15 | # return the MSE, the lower the error, the more "similar" 16 | # the two images are 17 | return err 18 | 19 | def get_psnr(imageA,imageB): 20 | mse = get_mse(imageA,imageB) 21 | psnr = (20 * np.log10(256))-(10 * np.log10(mse)) 22 | return psnr 23 | 24 | def get_perc_error(imageA,imageB): 25 | err = np.sum(abs((imageA.astype("float") - imageB.astype("float"))) ) 26 | err /= float(imageA.shape[0] * imageA.shape[1] * imageA.shape[2]) 27 | perc_err = err/ 256 28 | perc_err *= 100 29 | # return the MSE, the lower the error, the more "similar" 30 | # the two images are 31 | return perc_err 32 | 33 | 34 | real_isp_output = cv2.imread("../../imgs/NikonD7000FL/DSC_0916.png") 35 | forward_pipeline_out = cv2.imread("../../imgs/NikonD7000FL/forward_pipe_output.png") 36 | forward_pipeline_out = forward_pipeline_out[0:3264,0:4928] #Crop out camera test pixels 37 | real_demosiaced_raw = cv2.imread("../../imgs/NikonD7000FL/DSC_0916.NEF.demos_3C.png") 38 | real_demosiaced_raw = real_demosiaced_raw[0:3264,0:4928] #Crop out camera test pixels 39 | backward_pipeline_out = cv2.imread("../../imgs/NikonD7000FL/backward_pipe_output.png") 40 | 41 | print "===Forward pipeline===" 42 | print "Per pix % error: "+str(get_perc_error(real_isp_output,forward_pipeline_out)) 43 | print "MSE: "+str(get_mse(real_isp_output,forward_pipeline_out)) 44 | print "PSNR: "+str(get_psnr(real_isp_output,forward_pipeline_out)) 45 | print "===Backward pipeline===" 46 | print "Per pix % error: "+str(get_perc_error(real_demosiaced_raw,backward_pipeline_out)) 47 | print "MSE: "+str(get_mse(real_demosiaced_raw,backward_pipeline_out)) 48 | print "PSNR: "+str(get_psnr(real_demosiaced_raw,backward_pipeline_out)) 49 | -------------------------------------------------------------------------------- /src/scripts/ImgPipe.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // 3 | // Image Processing Pipeline Simulator 4 | // 5 | // This code simulates the image processing pipeline from sensor to 6 | // output image. Input is expected to be raw camera pixel values which 7 | // are interpreted as irradiance values. The current version receives 8 | // a single raw file and produces images at various stages 9 | // within the image processing pipeline by using the LibRaw and OpenCV 10 | // libraries. 11 | // 12 | // Input: 13 | // Single raw image file (tested with Nikon .NEF) 14 | // 15 | // Output: 16 | // .raw_3C.png: 17 | // The raw data in uncompressed 16 bit, represented with 3 rgb channels 18 | // .bgr_3C.png: 19 | // The result of OpenCV demosiacing (debayering) 20 | // .dcraw.png: 21 | // The result of LibRaw dcraw processing (open source image processing) 22 | // .dcraw.jpg: 23 | // The result of LibRaw dcraw, but compressed as a jpg 24 | // 25 | // LibRaw docs: http://www.libraw.org/docs/API-CXX-eng.html 26 | // OpenCV docs: http://docs.opencv.org/3.1.0/ 27 | // 28 | // Author: Mark Buckler 29 | // 30 | ///////////////////////////////////////////////////////////////////////// 31 | // 32 | // NOTE: You may need to change the demosaic pattern. It is different 33 | // for every camera, so be sure to check. 34 | // 35 | ///////////////////////////////////////////////////////////////////////// 36 | 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | using namespace std; 43 | using namespace cv; 44 | 45 | int main(int argc, char** argv ) 46 | { 47 | 48 | // Inform user of usage method 49 | if ( argc != 3 ) 50 | { 51 | printf("usage: ImgPipe path/to/image \n"); 52 | return -1; 53 | } 54 | 55 | //////////////////////////////////////////////////////////////////// 56 | // LibRaw raw data extraction //////////////////////////////////// 57 | 58 | // Establish use of LibRaw 59 | LibRaw RawProcessor; 60 | #define imgdata RawProcessor.imgdata 61 | 62 | // Function failure flag 63 | int ret; 64 | 65 | // Path to input 66 | const char * in_path = argv[1]; 67 | 68 | // Bitdepth of raw input 69 | int num_raw_bits = atoi(argv[2]); 70 | int scale = 1 << (16-num_raw_bits); 71 | 72 | // Read in raw image with LibRaw 73 | if ((ret = RawProcessor.open_file(in_path)) != LIBRAW_SUCCESS) 74 | { 75 | fprintf(stderr, in_path, libraw_strerror(ret)); 76 | return -1; 77 | } 78 | 79 | // Unpack the raw image, storing it in imgdata.rawdata.raw_image 80 | if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS) 81 | { 82 | return -1; 83 | } 84 | 85 | 86 | //////////////////////////////////////////////////////////////////// 87 | // Raw data ////////////////////////////////////////////////////// 88 | 89 | // 3 Channel Scaled Raw //////////////////////////////////////////// 90 | 91 | // Place the raw_image into 4 channel image 92 | RawProcessor.raw2image(); 93 | 94 | // Extract raw data stored in 16 bit, 4 channel image 95 | // NOTE: Data here is taken from imgdata.image instead of 96 | // imgdata.raw_image. This is OK because no processing has 97 | // been performed, and is useful to enable access to data in 98 | // the 4 channel format. 99 | Mat raw_4C = Mat( 100 | imgdata.sizes.height, 101 | imgdata.sizes.width, 102 | CV_16UC4, 103 | imgdata.image 104 | ); 105 | 106 | // Split the image into different channels 107 | vector rg1bg2Channels; 108 | split(raw_4C, rg1bg2Channels); 109 | 110 | // Add the two green channels together 111 | Mat green_sum = rg1bg2Channels[1] + rg1bg2Channels[3]; 112 | Mat zeros = Mat::zeros(Size(raw_4C.cols, raw_4C.rows), CV_16UC1); 113 | 114 | // Merge the three channels into the final raw image 115 | // NOTE: OpenCV holds images in BGR order rather than more common RGB 116 | Mat raw_3C; 117 | vector bgrChannels; 118 | // Blue channel 119 | bgrChannels.push_back(rg1bg2Channels[2]); 120 | // Green channel 121 | bgrChannels.push_back( green_sum); 122 | // Red channel 123 | bgrChannels.push_back(rg1bg2Channels[0]); 124 | // Merge channels 125 | merge(bgrChannels, raw_3C); 126 | 127 | // Scale up raw elements to fit 16 bit mat entries 128 | raw_3C.convertTo(raw_3C, CV_16UC1, scale); 129 | 130 | // Write the raw 3 channel representation to file 131 | imwrite( (std::string(in_path)+".raw_3C.png").c_str(), raw_3C); 132 | 133 | 134 | //////////////////////////////////////////////////////////////////// 135 | // Demosiaced //////////////////////////////////////////////////// 136 | 137 | // Raw data stored in 16 bit, 1 channel image 138 | Mat raw_1C = Mat( 139 | imgdata.sizes.raw_height, 140 | imgdata.sizes.raw_width, 141 | CV_16UC1, 142 | imgdata.rawdata.raw_image, 143 | Mat::AUTO_STEP 144 | ); 145 | 146 | // Scale up raw elements to fit 16 bit mat entries 147 | raw_1C.convertTo(raw_1C, CV_16UC1, scale); 148 | 149 | // Demosiac (debayer) the image 150 | Mat bgr_3C; 151 | cvtColor(raw_1C, bgr_3C, CV_BayerRG2RGB); 152 | 153 | // Write the demosiaced 3 channel representation to file 154 | imwrite( (std::string(in_path)+".bgr_3C.png").c_str(), bgr_3C); 155 | 156 | // Free the RawProcessor to reload image for dcraw processing 157 | RawProcessor.recycle(); 158 | 159 | 160 | //////////////////////////////////////////////////////////////////// 161 | // Dcraw processed /////////////////////////////////////////////// 162 | 163 | // Reload image (needs to be re-initialized for dcraw processing) 164 | RawProcessor.open_file(in_path); 165 | RawProcessor.unpack(); 166 | 167 | // Dcraw settings 168 | imgdata.params.use_camera_wb = 1; 169 | 170 | // Process raw data using LibRaw implementation of dcraw 171 | int check = RawProcessor.dcraw_process(); 172 | libraw_processed_image_t *image_ptr = RawProcessor.dcraw_make_mem_image(&check); 173 | 174 | // Convert the raw image to an OpenCV Mat 175 | // Note: The argument CV_8UC3 parses as follows 176 | // CV_{U|S|F}C() 177 | Mat dcraw; 178 | dcraw = Mat(Size(image_ptr->width, image_ptr->height), 179 | CV_8UC3, image_ptr->data, Mat::AUTO_STEP); 180 | 181 | // Convert from the default RGB color space to the correct BGR color space 182 | // This conversion is trivial and therefore can be done 183 | // even in pipelines where no color mapping is requested. 184 | cv::cvtColor(dcraw, dcraw, CV_RGB2BGR); 185 | 186 | // Write the dcrawed representation to file 187 | imwrite( (std::string(in_path)+".dcraw.png").c_str(), dcraw); 188 | 189 | 190 | //////////////////////////////////////////////////////////////////// 191 | // Dcraw processed and compressed //////////////////////////////// 192 | 193 | // Print the compressed version of the dcraw processed output 194 | imwrite( (std::string(in_path)+".dcraw.jpg").c_str(), dcraw); 195 | 196 | // Free RawProcessor 197 | RawProcessor.recycle(); 198 | 199 | return 0; 200 | } 201 | -------------------------------------------------------------------------------- /src/scripts/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile test 3 | 4 | all: 5 | g++ -o ImgPipe ImgPipe.cpp `pkg-config opencv --cflags --libs` -lraw -lm 6 | g++ -o RawPreproc RawPreproc.cpp `pkg-config opencv --cflags --libs` -lraw -lm 7 | -------------------------------------------------------------------------------- /src/scripts/README.txt: -------------------------------------------------------------------------------- 1 | 2 | ##################################################################### 3 | # Image Pipeline Scripts 4 | ##################################################################### 5 | 6 | ##################################################################### 7 | # General Description 8 | ##################################################################### 9 | 10 | This directory contains both ImgPipe.cpp and RawPreproc.cpp. 11 | ImgPipe.cpp can be used as a non-configurable, non-reversible, 12 | image processing pipeline. RawPreproc is used to create images 13 | usable as raw input to the Halide and Matlab imaging pipelines. 14 | 15 | ##################################################################### 16 | # How to build 17 | ##################################################################### 18 | 19 | 1) Install LibRaw and OpenCV 20 | LibRaw docs: http://www.libraw.org/docs/API-CXX-eng.html 21 | OpenCV docs: http://docs.opencv.org/3.1.0/ 22 | 2) Change to this directory (ReversiblePipeline/src/scripts) 23 | 3) Compile with the provided Makefile 24 | > make 25 | 4) Determine the bitdepth of your raw input file 26 | 5) Run either script, input format is the same 27 | > ./RawPreproc path/to/image 28 | example: 29 | > ./RawPreproc ../../imgs/NikonD7000FL/DSC_0916.NEF 14 30 | 6) Observe the results in the same directory that your input 31 | file is in. 32 | 33 | ##################################################################### 34 | # Additional notes 35 | ##################################################################### 36 | 37 | Both the RawPreproc and ImgPipe scripts in this directory perform 38 | demosaicing with OpenCV. To demosaic correctly, the correct bayer 39 | pattern must be used. The current implementation doesn't provide 40 | easy configurability for changing the bayer filter version, but 41 | once you know what pattern your raw files use, you can change the 42 | pattern in the code according to this guide: 43 | 44 | http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html 45 | -------------------------------------------------------------------------------- /src/scripts/RawPreproc.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // 3 | // Raw Image Preprocessor 4 | // 5 | // This script is built to preprocess raw files for both the Halide and 6 | // Matlab reversible imaging pipelines. Raw files are used as input 7 | // to the forward imaging pipelines, and as reference output for the 8 | // the backward imaging pipelines. Since neither Halide nor Matlab can 9 | // read raw file formats (such as Nikon .NEF), LibRaw is used to 10 | // receive raw data, and OpenCV is used to scale, preprocess as needed, 11 | // and write readable files. 12 | // 13 | // Input: 14 | // Single raw image file (tested with 14 bit Nikon .NEF) 15 | // 16 | // Output: 17 | // /.raw_1C.tiff: 18 | // A scaled version of the raw input, stored in a 1 channel tiff 19 | // Used by the Matlab pipeline 20 | // /.demos_3C.png: 21 | // Scaled and demosiaced raw input, stored in a 3 channel png 22 | // Used by the Halide pipeline 23 | // 24 | // Author: Mark Buckler 25 | // 26 | ///////////////////////////////////////////////////////////////////////// 27 | // 28 | // NOTE: You may need to change the demosaic pattern. It is different 29 | // for every camera, so be sure to check. 30 | // 31 | ///////////////////////////////////////////////////////////////////////// 32 | 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | using namespace std; 40 | using namespace cv; 41 | 42 | int main(int argc, char** argv ) 43 | { 44 | 45 | // Inform user of usage method 46 | if ( argc != 3 ) 47 | { 48 | printf("usage: \n./RawPreproc path/to/image \n"); 49 | return -1; 50 | } 51 | 52 | //////////////////////////////////////////////////////////////////// 53 | // LibRaw raw data extraction //////////////////////////////////// 54 | 55 | // Establish use of LibRaw 56 | LibRaw RawProcessor; 57 | #define imgdata RawProcessor.imgdata 58 | 59 | // Function failure flag 60 | int ret; 61 | 62 | // Path to input 63 | const char * in_path = argv[1]; 64 | 65 | // Bitdepth of raw input 66 | int num_raw_bits = atoi(argv[2]); 67 | 68 | // Read in raw image with LibRaw 69 | if ((ret = RawProcessor.open_file(in_path)) != LIBRAW_SUCCESS) 70 | { 71 | fprintf(stderr, in_path, libraw_strerror(ret)); 72 | return -1; 73 | } 74 | 75 | // Unpack the raw image, storing it in imgdata.rawdata.raw_image 76 | if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS) 77 | { 78 | return -1; 79 | } 80 | 81 | //////////////////////////////////////////////////////////////////// 82 | // Raw data for Matlab //////////////////////////////////////////// 83 | 84 | // Extract raw data stored in 16 bit, 1 channel image 85 | Mat raw_1C = Mat( 86 | imgdata.sizes.raw_height, 87 | imgdata.sizes.raw_width, 88 | CV_16UC1, 89 | imgdata.rawdata.raw_image 90 | ); 91 | 92 | // Scale the data to fit the 16 bit representation 93 | int scale = 1 << (16-num_raw_bits); 94 | raw_1C = raw_1C * scale; 95 | 96 | // Write the raw 1 channel representation to file 97 | imwrite( (std::string(in_path)+".raw_1C.tiff").c_str(), raw_1C); 98 | 99 | //////////////////////////////////////////////////////////////////// 100 | // Demosaiced data for Halide ///////////////////////////////////// 101 | 102 | // Demosiac (debayer) the image 103 | Mat bgr_3C; 104 | cvtColor(raw_1C, bgr_3C, CV_BayerRG2RGB); 105 | 106 | // Write the demosiaced 12 bit 3 channel representation to file 107 | imwrite( (std::string(in_path)+".demos_3C.png").c_str(), bgr_3C); 108 | 109 | 110 | return 0; 111 | } 112 | --------------------------------------------------------------------------------