{"id":877,"date":"2020-12-27T18:38:08","date_gmt":"2020-12-27T17:38:08","guid":{"rendered":"https:\/\/www.numbercrunch.de\/blog\/?p=877"},"modified":"2023-01-18T20:38:29","modified_gmt":"2023-01-18T19:38:29","slug":"from-numbers-to-images-raw-image-processing-with-python","status":"publish","type":"post","link":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/","title":{"rendered":"From numbers to images &#8211; Raw image processing with Python"},"content":{"rendered":"\n<p style=\"text-align: justify;\">Modern digital system cameras and also some digital compact cameras allow to create and to store images in a so-called raw format. A raw image contains<\/p>\n<ul>\n<li style=\"text-align: justify;\">the minimally pre-processed sensor data,<\/li>\n<li>meta-data about the picture such as camera model, lens model and camera settings under which the picture has been taken and<\/li>\n<li>possibly a fully processed preview image.<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Raw images are the image format of choice for most serious professional or enthusiast photographers as this format provides the optimal base material for further processing, e.g., tonal adjustments, color grading and all kinds of geometric and lens corrections. Yet, dealing with raw files can be cumbersome. Each camera manufacturer uses its own proprietary raw file format for his cameras. Raw files cannot be displayed directly, the must be processed first. Therefore raw files are sometimes called digital negatives. Raw processing is usually carried out by specialized programs such as <a href=\"https:\/\/www.darktable.org\">darktable<\/a> or <a href=\"https:\/\/rawtherapee.com\">RawTherapee<\/a>.<\/p>\n<p style=\"text-align: justify;\">The Python packages <a href=\"https:\/\/letmaik.github.io\/rawpy\/api\/\">rawpy<\/a>, PIL (aka <a href=\"https:\/\/pillow.readthedocs.io\/en\/stable\/\">Pillow<\/a>) and <a href=\"https:\/\/github.com\/ianare\/exif-py\">exifread<\/a> allow to perform various tasks of raw image processing in Python. This is particularly useful for batch processing and prototyping of new image processing algorithms. In the following a few demonstrative examples are shown how to use rawpy, PIL and exifread.<\/p>\n<p>Load rawpy and some further useful Python packages first:<\/p>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">import os\nfrom io import BytesIO\nimport matplotlib.pyplot as plt\nimport rawpy\nimport exifread\nimport numpy as np\nfrom PIL import Image\n<\/pre>\n<\/div>\n<p>Read a raw image and extract some basic information about the image:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">raw_filename = 'A1_07396.arw'\n \nwith rawpy.imread(raw_filename) as raw:\n    print(f'raw type:                     {raw.raw_type}')                      # raw type (flat or stack, e.g., Foveon sensor)\n    print(f'number of colors:             {raw.num_colors}')                    # number of different color components, e.g., 3 for common RGB Bayer sensors with two green identical green sensors \n    print(f'color description:            {raw.color_desc}')                    # describes the various color components\n    print(f'raw pattern:                  {raw.raw_pattern.tolist()}')          # decribes the pattern of the Bayer sensor\n    print(f'black levels:                 {raw.black_level_per_channel}')       # black level correction\n    print(f'white level:                  {raw.white_level}')                   # camera white level\n    print(f'color matrix:                 {raw.color_matrix.tolist()}')         # camera specific color matrix, usually obtained from a list in rawpy (not from the raw file)\n    print(f'XYZ to RGB conversion matrix: {raw.rgb_xyz_matrix.tolist()}')       # camera specific XYZ to camara RGB conversion matrix\n    print(f'camera white balance:         {raw.camera_whitebalance}')           # the picture's white balance as determined by the camera\n    print(f'daylight white balance:       {raw.daylight_whitebalance}')         # the camera's daylight white balance\n<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\">raw type:                     RawType.Flat\nnumber of colors:             3\ncolor description:            b'RGBG'\nraw pattern:                  [[0, 1], [3, 2]]\nblack levels:                 [512, 512, 512, 512]\nwhite level:                  16383\ncolor matrix:                 [[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]\nXYZ to RGB conversion matrix: [[0.5972999930381775, -0.16949999332427979, -0.04190000146627426], [-0.38260000944137573, 1.1797000169754028, 0.22930000722408295], [-0.06390000134706497, 0.13979999721050262, 0.5788999795913696], [0.0, 0.0, 0.0]]\ncamera white balance:         [2452.0, 1024.0, 2036.0, 1024.0]\ndaylight white balance:       [2.836125135421753, 0.9383336305618286, 1.409664511680603, 0.0]\n<\/pre>\n<p>Extract and print EXIF meta-data of the raw file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">with open(raw_filename, 'rb') as f:\n    tags = exifread.process_file(f)\n    for key, value in tags.items():\n        if key is not 'JPEGThumbnail':  # do not print (uninteresting) binary thumbnail data\n            print(f'{key}: {value}')\n<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">Image SubfileType: Reduced-resolution image\nImage Compression: JPEG (old-style)\nImage ImageDescription:                                \nImage Make: SONY\nImage Model: ILCE-6300\nImage Orientation: Horizontal (normal)\nImage XResolution: 350\nImage YResolution: 350\nImage ResolutionUnit: Pixels\/Inch\nImage Software: ILCE-6300 v2.01\nImage DateTime: 2019:02:24 12:56:34\nImage Artist: Heiko Bauke\nImage Tag 0x014A: 145554\nImage JPEGInterchangeFormat: 146594\nImage JPEGInterchangeFormatLength: 454075\nImage YCbCrPositioning: Co-sited\nImage Copyright: Heiko Bauke\nImage ExifOffset: 484\nImage PrintIM: [80, 114, 105, 110, 116, 73, 77, 0, 48, 51, 48, 48, 0, 0, 3, 0, 2, 0, 1, 0, ... ]\nImage Tag 0xC634: [156, 201, 0, 0]\nThumbnail SubfileType: Reduced-resolution image\nThumbnail Compression: JPEG (old-style)\nThumbnail ImageDescription:                                \nThumbnail Make: SONY\nThumbnail Model: ILCE-6300\nThumbnail Orientation: Horizontal (normal)\nThumbnail XResolution: 72\nThumbnail YResolution: 72\nThumbnail ResolutionUnit: Pixels\/Inch\nThumbnail Software: ILCE-6300 v2.01\nThumbnail DateTime: 2019:02:24 12:56:34\nThumbnail Artist: Heiko Bauke\nThumbnail JPEGInterchangeFormat: 38906\nThumbnail JPEGInterchangeFormatLength: 11192\nThumbnail YCbCrPositioning: Co-sited\nThumbnail Copyright: Heiko Bauke\nEXIF ExposureTime: 1\/2500\nEXIF FNumber: 14\/5<br \/>EXIF ExposureProgram: Aperture Priority\nEXIF ISOSpeedRatings: 200\nEXIF SensitivityType: Recommended Exposure Index\nEXIF RecommendedExposureIndex: 200\nEXIF ExifVersion: 0230\nEXIF DateTimeOriginal: 2019:02:24 12:56:34\nEXIF DateTimeDigitized: 2019:02:24 12:56:34\nEXIF ComponentsConfiguration: YCbCr\nEXIF CompressedBitsPerPixel: 8\nEXIF BrightnessValue: 6547\/1280\nEXIF ExposureBiasValue: 0\nEXIF MaxApertureValue: 0\nEXIF MeteringMode: Pattern\nEXIF LightSource: Unknown\nEXIF Flash: Flash did not fire, compulsory flash mode\nEXIF FocalLength: 55\nEXIF MakerNote: [95, 0, 3, 16, 4, 0, 16, 0, 0, 0, 136, 8, 0, 0, 0, 32, 7, 0, 1, 0, ... ]\nEXIF UserComment: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\nEXIF FlashPixVersion: 0100\nEXIF ColorSpace: sRGB\nEXIF ExifImageWidth: 6000\nEXIF ExifImageLength: 4000\nInteroperability InteroperabilityIndex: R98\nInteroperability InteroperabilityVersion: [48, 49, 48, 48]\nEXIF InteroperabilityOffset: 38554\nEXIF FileSource: Digital Camera\nEXIF SceneType: Directly Photographed\nEXIF CustomRendered: Normal\nEXIF ExposureMode: Auto Exposure\nEXIF WhiteBalance: Auto\nEXIF DigitalZoomRatio: 1\nEXIF FocalLengthIn35mmFilm: 82\nEXIF SceneCaptureType: Standard\nEXIF Contrast: Normal\nEXIF Saturation: Normal\nEXIF Sharpness: Normal\nEXIF LensModel: Nikon AI-S Nikkor 55mm f\/2.8 Micro\n<\/pre>\n<p>The embedded thumbnail image is extracted from a raw file next. The thumbnail is saved to disk and displayed. (Note that some raw formats have unusual bitmap thumbnails which may not be read correctly or not read at all.)<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">filename, _ = os.path.splitext(raw_filename)\nwith rawpy.imread(raw_filename) as raw:\n    try:\n        thumb = raw.extract_thumb()\n    except rawpy.LibRawNoThumbnailError:\n        print('no thumbnail found')\n    else:\n        if thumb.format in [rawpy.ThumbFormat.JPEG, rawpy.ThumbFormat.BITMAP]:\n            if thumb.format is rawpy.ThumbFormat.JPEG:\n                thumb_filename = filename + '_thumb.jpg'\n                with open(thumb_filename, 'wb') as f:\n                    f.write(thumb.data)\n                thumb_rgb = Image.open(BytesIO(thumb.data))\n            else:\n                thumb_filename = filename + '_thumb.tiff'\n                thumb_rgb = Image.fromarray(thumb.data)\n                thumb_rgb.save(filename, 'tiff')\n            plt.imshow(thumb_rgb)\n            plt.axis('off')\n        else:\n            print('unknown thumbnail format')\n<\/pre>\n<p><a href=\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-888\" src=\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png\" alt=\"\" width=\"326\" height=\"218\" srcset=\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png 326w, https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1-300x201.png 300w\" sizes=\"(max-width: 326px) 100vw, 326px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">The next example shows how to process a raw image via rawpy to create an image that is suitable for display. Camera white balance settings are used.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">with rawpy.imread(raw_filename) as raw:\n    image = raw.raw_image\n    rgb = raw.postprocess(rawpy.Params(use_camera_wb=True))\n    plt.imshow(rgb)\n    plt.axis('off')\n<\/pre>\n<p><a href=\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-889\" src=\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_2.png\" alt=\"\" width=\"326\" height=\"218\" srcset=\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_2.png 326w, https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_2-300x201.png 300w\" sizes=\"(max-width: 326px) 100vw, 326px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">A raw image is not suitable for display. The function <code>postprocess<\/code> was utilized before to turn a raw image into an image that can be displayed. In the following, a minimalistic raw conversion into sRGB is performed that yields an image that is suitable for display. The employed procedure is rather general, but it assumes that the camera features a Bayer-pattern<\/p>\n<p>[codesyntax\u00a0lang=&#8221;text&#8221;]<\/p>\n<p>\u00a0<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">\u00a0<\/pre>\n<p style=\"text-align: justify;\">sensor. The fundamental element of a Bayer-sensor pattern consists of 2 times 2 pixels of 3 or of 4 different colors. The following steps are required to convert Bayer pixel data into RGB pixels:<\/p>\n<ul>\n<li>Subtract the black level from raw data.<\/li>\n<li>Amplify the 3 or 4 color components by the white balance coefficients.<\/li>\n<li>Demosaic the Bayer pattern. Raw image data contains only one color component at each pixel position. Demosaicing reconstructs a full color image from the incomplete color samples output from the image sensor overlaid with a color filter array, i.e., the Bayer pattern. Here, a simple down sampling approach is implemented for demonstration. This is not a method suitable for high-quality raw conversion.<\/li>\n<li>Transform the 3 or 4 camera color components into the 3 color components of linear sRGB. Transformations between different color spaces are mediated by matrices. The transformation from linear sRGB into the camera&#8217;s primary colors is given by the matrix product of the transformation matrix that transforms color <a href=\"http:\/\/www.brucelindbloom.com\/index.html?Eqn_RGB_XYZ_Matrix.html\">from sRGB into the XYZ color space<\/a> and the camera specific matrix that turns XYZ color into camera primaries. The transformation matrix for converting from the camera&#8217;s primary colors into sRGB is just the (pseudo-)inverse of this product. Note that the transformation matrix is normalized before inversion in such a way that white in sRGB (all components equal to unity) maps to white in the space of camera&#8217;s primaries. See also <a href=\"https:\/\/www.rcsumner.net\/raw_guide\/\">Processing RAW Images in MATLAB<\/a> for details.<\/li>\n<li>In a last step, the <a href=\"https:\/\/en.wikipedia.org\/wiki\/SRGB#Specification_of_the_transformation\">sRGB gamma correction<\/a> is applied.<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">The end result of this procedure is usable but looks rather dull and is lacking contrast. This can be fixed by further processing steps, e.g., the application of an <a href=\"https:\/\/eng.aurelienpierre.com\/2018\/11\/filmic-darktable-and-the-quest-of-the-hdr-tone-mapping\/\">S-shaped tone curve<\/a>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">with rawpy.imread(raw_filename) as raw:\n    # get raw image data\n    image = np.array(raw.raw_image, dtype=np.double)\n    # subtract black levels and normalize to interval [0..1]\n    black = np.reshape(np.array(raw.black_level_per_channel, dtype=np.double), (2, 2))\n    black = np.tile(black, (image.shape[0]\/\/2, image.shape[1]\/\/2))\n    image = (image - black) \/ (raw.white_level - black)\n    # find the positions of the three (red, green and blue) or four base colors within the Bayer pattern\n    n_colors = raw.num_colors\n    colors = np.frombuffer(raw.color_desc, dtype=np.byte)\n    pattern = np.array(raw.raw_pattern)\n    index_0 = np.where(colors[pattern] == colors[0])\n    index_1 = np.where(colors[pattern] == colors[1])\n    index_2 = np.where(colors[pattern] == colors[2])\n    index_3 = np.where(colors[pattern] == colors[3])\n    # apply white balance, normalize white balance coefficients to the 2nd coefficient, which is ususally the coefficient for green\n    wb_c = raw.camera_whitebalance \n    wb = np.zeros((2, 2), dtype=np.double) \n    wb[index_0] = wb_c[0] \/ wb_c[1]\n    wb[index_1] = wb_c[1] \/ wb_c[1]\n    wb[index_2] = wb_c[2] \/ wb_c[1]\n    if n_colors == 4:\n        wb[index_3] = wb_c[3] \/ wb_c[1]\n    wb = np.tile(wb, (image.shape[0]\/\/2, image.shape[1]\/\/2))\n    image_wb = np.clip(image * wb, 0, 1)\n    # demosaic via downsampling\n    image_demosaiced = np.empty((image_wb.shape[0]\/\/2, image_wb.shape[1]\/\/2, n_colors))\n    if n_colors == 3:\n        image_demosaiced[:, :, 0] = image_wb[index_0[0][0]::2, index_0[1][0]::2]\n        image_demosaiced[:, :, 1]  = (image_wb[index_1[0][0]::2, index_1[1][0]::2] + image_wb[index_1[0][1]::2, index_1[1][1]::2]) \/ 2\n        image_demosaiced[:, :, 2]  = image_wb[index_2[0][0]::2, index_2[1][0]::2]\n    else: # n_colors == 4\n        image_demosaiced[:, :, 0] = image_wb[index_0[0][0]::2, index_0[1][0]::2]\n        image_demosaiced[:, :, 1] = image_wb[index_1[0][0]::2, index_1[1][0]::2]\n        image_demosaiced[:, :, 2] = image_wb[index_2[0][0]::2, index_2[1][0]::2]\n        image_demosaiced[:, :, 3] = image_wb[index_3[0][0]::2, index_3[1][0]::2]\n    # convert to linear sRGB, calculate the matrix that transforms sRGB into the camera's primary color components and invert this matrix to perform the inverse transformation\n    XYZ_to_cam = np.array(raw.rgb_xyz_matrix[0:n_colors, :], dtype=np.double)\n    sRGB_to_XYZ = np.array([[0.4124564, 0.3575761, 0.1804375],\n                            [0.2126729, 0.7151522, 0.0721750],\n                            [0.0193339, 0.1191920, 0.9503041]], dtype=np.double)\n    sRGB_to_cam = np.dot(XYZ_to_cam, sRGB_to_XYZ)\n    norm = np.tile(np.sum(sRGB_to_cam, 1), (3, 1)).transpose()\n    sRGB_to_cam = sRGB_to_cam \/ norm\n    if n_colors == 3:\n        cam_to_sRGB = np.linalg.inv(sRGB_to_cam)\n    else: # n_colors == 4\n        cam_to_sRGB = np.linalg.pinv(sRGB_to_cam)\n    image_sRGB = np.einsum('ij,...j', cam_to_sRGB, image_demosaiced)  # performs the matrix-vector product for each pixel\n    # apply sRGB gamma curve\n    i = image_sRGB &lt; 0.0031308\n    j = np.logical_not(i)\n    image_sRGB[i] = 323 \/ 25 * image_sRGB[i]\n    image_sRGB[j] = 211 \/ 200 * image_sRGB[j] ** (5 \/ 12) - 11 \/ 200\n    image_sRGB = np.clip(image_sRGB, 0, 1)\n    # show image\n    plt.axis('off')\n    plt.imshow(image_sRGB)\n<\/pre>\n<p><a href=\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-890\" src=\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_3.png\" alt=\"\" width=\"327\" height=\"218\" srcset=\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_3.png 327w, https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_3-300x200.png 300w\" sizes=\"(max-width: 327px) 100vw, 327px\" \/><\/a><\/p>\n<p>A Jupyter notebook version of this blog post is available on <a href=\"_wp_link_placeholder\" data-wplink-edit=\"true\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Modern digital system cameras and also some digital compact cameras allow to create and to store images in a so-called raw format. A raw image contains the minimally pre-processed sensor data, meta-data about the picture such as camera model, lens model and camera settings under which the picture has been taken and possibly a fully&hellip; <a href=\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">From numbers to images &#8211; Raw image processing with Python<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17,15,11,5],"tags":[],"class_list":["post-877","post","type-post","status-publish","format-standard","hentry","category-image-processing","category-numerical-methods","category-python","category-software"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v25.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>From numbers to images - Raw image processing with Python - Number Crunch<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"From numbers to images - Raw image processing with Python - Number Crunch\" \/>\n<meta property=\"og:description\" content=\"Modern digital system cameras and also some digital compact cameras allow to create and to store images in a so-called raw format. A raw image contains the minimally pre-processed sensor data, meta-data about the picture such as camera model, lens model and camera settings under which the picture has been taken and possibly a fully&hellip; Continue reading From numbers to images &#8211; Raw image processing with Python\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/\" \/>\n<meta property=\"og:site_name\" content=\"Number Crunch\" \/>\n<meta property=\"article:published_time\" content=\"2020-12-27T17:38:08+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-01-18T19:38:29+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png\" \/>\n<meta name=\"author\" content=\"Heiko Bauke\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Heiko Bauke\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/\"},\"author\":{\"name\":\"Heiko Bauke\",\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413\"},\"headline\":\"From numbers to images &#8211; Raw image processing with Python\",\"datePublished\":\"2020-12-27T17:38:08+00:00\",\"dateModified\":\"2023-01-18T19:38:29+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/\"},\"wordCount\":663,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413\"},\"image\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png\",\"articleSection\":[\"image processing\",\"numerical methods\",\"Python\",\"Software\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/\",\"url\":\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/\",\"name\":\"From numbers to images - Raw image processing with Python - Number Crunch\",\"isPartOf\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png\",\"datePublished\":\"2020-12-27T17:38:08+00:00\",\"dateModified\":\"2023-01-18T19:38:29+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#primaryimage\",\"url\":\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png\",\"contentUrl\":\"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png\",\"width\":326,\"height\":218},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.numbercrunch.de\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"From numbers to images &#8211; Raw image processing with Python\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#website\",\"url\":\"https:\/\/www.numbercrunch.de\/blog\/\",\"name\":\"Number Crunch\",\"description\":\"A computational science blog.\",\"publisher\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.numbercrunch.de\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413\",\"name\":\"Heiko Bauke\",\"logo\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"From numbers to images - Raw image processing with Python - Number Crunch","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/","og_locale":"en_US","og_type":"article","og_title":"From numbers to images - Raw image processing with Python - Number Crunch","og_description":"Modern digital system cameras and also some digital compact cameras allow to create and to store images in a so-called raw format. A raw image contains the minimally pre-processed sensor data, meta-data about the picture such as camera model, lens model and camera settings under which the picture has been taken and possibly a fully&hellip; Continue reading From numbers to images &#8211; Raw image processing with Python","og_url":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/","og_site_name":"Number Crunch","article_published_time":"2020-12-27T17:38:08+00:00","article_modified_time":"2023-01-18T19:38:29+00:00","og_image":[{"url":"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png","type":"","width":"","height":""}],"author":"Heiko Bauke","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Heiko Bauke","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#article","isPartOf":{"@id":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/"},"author":{"name":"Heiko Bauke","@id":"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413"},"headline":"From numbers to images &#8211; Raw image processing with Python","datePublished":"2020-12-27T17:38:08+00:00","dateModified":"2023-01-18T19:38:29+00:00","mainEntityOfPage":{"@id":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/"},"wordCount":663,"commentCount":0,"publisher":{"@id":"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413"},"image":{"@id":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#primaryimage"},"thumbnailUrl":"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png","articleSection":["image processing","numerical methods","Python","Software"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/","url":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/","name":"From numbers to images - Raw image processing with Python - Number Crunch","isPartOf":{"@id":"https:\/\/www.numbercrunch.de\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#primaryimage"},"image":{"@id":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#primaryimage"},"thumbnailUrl":"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png","datePublished":"2020-12-27T17:38:08+00:00","dateModified":"2023-01-18T19:38:29+00:00","breadcrumb":{"@id":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#primaryimage","url":"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png","contentUrl":"https:\/\/www.numbercrunch.de\/blog\/wp-content\/uploads\/2020\/12\/rawpy_demo_1.png","width":326,"height":218},{"@type":"BreadcrumbList","@id":"https:\/\/www.numbercrunch.de\/blog\/2020\/12\/from-numbers-to-images-raw-image-processing-with-python\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.numbercrunch.de\/blog\/"},{"@type":"ListItem","position":2,"name":"From numbers to images &#8211; Raw image processing with Python"}]},{"@type":"WebSite","@id":"https:\/\/www.numbercrunch.de\/blog\/#website","url":"https:\/\/www.numbercrunch.de\/blog\/","name":"Number Crunch","description":"A computational science blog.","publisher":{"@id":"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.numbercrunch.de\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413","name":"Heiko Bauke","logo":{"@id":"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/posts\/877"}],"collection":[{"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/comments?post=877"}],"version-history":[{"count":17,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/posts\/877\/revisions"}],"predecessor-version":[{"id":1018,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/posts\/877\/revisions\/1018"}],"wp:attachment":[{"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/media?parent=877"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/categories?post=877"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/tags?post=877"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}