{
  "source_file": "0930",
  "source_platform": "技术平台",
  "author": "Adrian Rosebrock / PyImageSearch",
  "title_listed": "Deep learning: How OpenCV's blobFromImage works",
  "keywords": "OpenCV,blobFromImage,深度学习",
  "domain": "图像处理",
  "content_type": "教程",
  "is_paid_flag": "否",
  "url": "https://pyimagesearch.com/2017/11/06/deep-learning-opencvs-blobfromimage-works/",
  "publish_date": "2017-11",
  "corpus_stage": "预训练/SFT",
  "notes": "OpenCV blobFromImage原理",
  "id": "4f1e783ead44",
  "collected_at": "2026-10-02T17:21:07",
  "title": "Deep learning: How OpenCV's blobFromImage works - PyImageSearch",
  "body_markdown": "Click here to download the source code to this post\nToday’s blog post is inspired by a number of PyImageSearch readers who have commented on previous deep learning tutorials wanting to understand what exactly OpenCV’s\nblobFromImage\nfunction is doing under the hood.\nYou see, to obtain (correct) predictions from deep neural networks you first need to preprocess your data.\nIn the context of deep learning and image classification, these preprocessing tasks normally involve:\nMean subtraction\nScaling by some factor\nOpenCV’s new deep neural network (\ndnn\n) module contains two functions that can be used for preprocessing images and preparing them for classification via pre-trained deep learning models.\nIn today’s blog post we are going to take apart OpenCV’s\ncv2.dnn.blobFromImage\nand\ncv2.dnn.blobFromImages\npreprocessing functions and understand how they work.\nTo learn more about image preprocessing for deep learning via OpenCV,\njust keep reading.\nLooking for the source code to this post?\nJump Right To The Downloads Section\nDeep learning: How OpenCV’s blobFromImage works\nOpenCV provides two functions to facilitate image preprocessing for deep learning classification:\ncv2.dnn.blobFromImage\ncv2.dnn.blobFromImages\nThese two functions perform\nMean subtraction\nScaling\nAnd optionally channel swapping\nIn the remainder of this tutorial we’ll:\nExplore mean subtraction and scaling\nExamine the function signature of each deep learning preprocessing function\nStudy these methods in detail\nAnd finally, apply OpenCV’s deep learning functions to a set of input images\nLet’s go ahead and get started.\nDeep learning and mean subtraction\nFigure 1:\nA visual representation of mean subtraction where the RGB mean (\ncenter\n) has been calculated from a dataset of images and subtracted from the original image\n(left)\nresulting in the output image\n(right)\n.\nBefore we dive into an explanation of OpenCV’s deep learning preprocessing functions, we first need to understand mean subtraction. Mean subtraction is used to help combat illumination changes in the input images in our dataset. We can therefore view mean subtraction as a technique used to aid our Convolutional Neural Networks.\nBefore we even begin training our deep neural network, we first compute the\naverage pixel intensity\nacross all images in the\ntraining set\nfor each of the Red, Green, and Blue channels.\nThis implies that we end up with three variables:\n,\n, and\nTypically the resulting values are a 3-tuple consisting of the mean of the Red, Green, and Blue channels, respectively.\nFor example, the mean values for the ImageNet training set are\nR=103.93\n,\nG=116.77\n, and\nB=123.68\n(you may have already encountered these values before if you have used a network that was pre-trained on  ImageNet).\nHowever, in some cases the mean Red, Green, and Blue values may be computed\nchannel-wise\nrather than\npixel-wise\n, resulting in an\nMxN\nmatrix. In this case the\nMxN\nmatrix for each channel is then subtracted from the input image during training/testing.\nBoth methods are perfectly valid forms of mean subtraction; however, we tend to see the pixel-wise version used more often,\nespecially\nfor larger datasets.\nWhen we are ready to pass an image through our network (whether for\ntraining\nor\ntesting\n), we subtract the\nmean\n,\n, from each input channel of the input image:\nWe may also have a\nscaling factor\n,\n, which adds in a normalization:\nThe value of\nmay be the standard deviation across the training set (thereby turning the preprocessing step into a standard score/z-score). However,\nmay also be manually set (versus calculated) to scale the input image space into a particular range — it really depends on the architecture, how the network was trained, and the techniques the implementing author is familiar with.\nIt’s important to note that\nnot all deep learning architectures perform mean subtraction and scaling!\nBefore you preprocess your images, be sure to read the relevant publication/documentation for the deep neural network you are using.\nAs you’ll find on your deep learning journey, some architectures perform mean subtraction only (thereby setting\n). Other architectures perform both mean subtraction and scaling. Even other architectures choose to perform\nno\nmean subtraction or scaling. Always check the relevant publication you are implementing/using to verify the techniques the author is using.\nMean subtraction, scaling, and normalization are covered in more detail inside\nDeep Learning for Computer Vision with Python\n.\nOpenCV’s blobFromImage and blobFromImages function\nLet’s start off by referring to the\nofficial OpenCV documentation\nfor\ncv2.dnn.blobFromImage\n:\n[blobFromImage] creates 4-dimensional blob from image. Optionally resizes and crops\nimage\nfrom center, subtract\nmean\nvalues, scales values by\nscalefactor\n, swap Blue and Red channels.\nInformally, a\nblob\nis just a (potentially collection) of image(s) with the same spatial dimensions (i.e., width and height), same depth (number of channels), that have all be preprocessed in the same manner.\nThe\ncv2.dnn.blobFromImage\nand\ncv2.dnn.blobFromImages\nfunctions are near identical.\nLet’s start with examining the\ncv2.dnn.blobFromImage\nfunction signature below:\nblob = cv2.dnn.blobFromImage(image, scalefactor=1.0, size, mean, swapRB=True)\nI’ve provided a discussion of each parameter below:\nimage\n: This is the input image we want to preprocess before passing it through our deep neural network for classification.\nscalefactor\n: After we perform mean subtraction we can optionally scale our images by some factor. This value defaults to `1.0` (i.e., no scaling) but we can supply another value as well. It’s also important to note that\nscalefactor\nshould be\nas we’re actually multiplying the input channels (after mean subtraction) by\nscalefactor\n.\nsize\n: Here we supply the spatial size that the Convolutional Neural Network expects. For most current state-of-the-art neural networks this is either\n224×224\n,\n227×227\n, or\n299×299\n.\nmean\n: These are our mean subtraction values. They can be a 3-tuple of the RGB means or they can be a single value in which case the supplied value is subtracted from every channel of the image. If you’re performing mean subtraction, ensure you supply the 3-tuple in `(R, G, B)` order, especially when utilizing the default behavior of\nswapRB=True\n.\nswapRB\n: OpenCV assumes images are in BGR channel order; however, the `mean` value assumes we are using RGB order. To resolve this discrepancy we can swap the R and B channels in\nimage\nby setting this value to `True`. By default OpenCV performs this channel swapping for us.\nThe\ncv2.dnn.blobFromImage\nfunction returns a\nblob\nwhich is our input image after mean subtraction, normalizing, and channel swapping.\nThe\ncv2.dnn.blobFromImages\nfunction is exactly the same:\nblob = cv2.dnn.blobFromImages(images, scalefactor=1.0, size, mean, swapRB=True)\nThe only exception is that we can pass in\nmultiple images\n, enabling us to batch process a set of\nimages\n.\nIf you’re processing multiple images/frames, be sure to use the\ncv2.dnn.blobFromImages\nfunction as there is less function call overhead and you’ll be able to batch process the images/frames faster.\nDeep learning with OpenCV’s blobFromImage function\nNow that we’ve studied both the\nblobFromImage\nand\nblobFromImages\nfunctions, let’s apply them to a few example images and then pass them through a Convolutional Neural Network for classification.\nAs a prerequisite, you need OpenCV version 3.3.0\nat a minimum\n. NumPy is a dependency of OpenCV’s Python bindings and\nimutils\nis my package of convenience functions available on\nGitHub\nand in the\nPython Package Index\n.\nIf you haven’t installed OpenCV, you’ll want to follow the latest tutorials available\nhere\n, and\nbe sure to specify OpenCV 3.3.0 or higher\nwhen you clone/download\nopencv\nand\nopencv_contrib\n.\nThe imutils package can be installed via\npip\n:\n$ pip install imutils\nAssuming your image processing environment is ready to go, let’s open up a new file, name it\nblob_from_images.py\n, and insert the following code:\n# import the necessary packages\nfrom imutils import paths\nimport numpy as np\nimport cv2\n\n# load the class labels from disk\nrows = open(\"synset_words.txt\").read().strip().split(\"\\n\")\nclasses = [r[r.find(\" \") + 1:].split(\",\")[0] for r in rows]\n\n# load our serialized model from disk\nnet = cv2.dnn.readNetFromCaffe(\"bvlc_googlenet.prototxt\",\n\t\"bvlc_googlenet.caffemodel\")\n\n# grab the paths to the input images\nimagePaths = sorted(list(paths.list_images(\"images/\")))\nFirst we import\nimutils\n,\nnumpy\n, and\ncv2\n(\nLines 2-4\n).\nThen we read\nsynset_words.txt\n(the ImageNet Class labels) and extract\nclasses\n, our class labels, on\nLines 7 and 8\n.\nTo load our model model from disk we use the DNN function,\ncv2.dnn.readNetFromCaffe\n, and specify\nbvlc_googlenet.prototxt\nas the filename parameter and\nbvlc_googlenet.caffemodel\nas the actual model file (\nLines 11 and 12\n).\nNote:\nYou can grab the pre-trained Convolutional Neural Network, class labels text file, source code, and example images to this post using the\n“Downloads”\nsection at the bottom of this tutorial.\nFinally, we grab the paths to the input images on\nLine 15\n. If you’re using Windows you should change the path separator here to ensure you can correctly load the image paths.\nNext, we’ll load images from disk and pre-process them using\nblobFromImage\n:\n# (1) load the first image from disk, (2) pre-process it by resizing\n# it to 224x224 pixels, and (3) construct a blob that can be passed\n# through the pre-trained network\nimage = cv2.imread(imagePaths[0])\nresized = cv2.resize(image, (224, 224))\nblob = cv2.dnn.blobFromImage(resized, 1, (224, 224), (104, 117, 123))\nprint(\"First Blob: {}\".format(blob.shape))\nIn this block, we first load the\nimage\n(\nLine 20\n) and then resize it to\n224×224\n(\nLine 21\n), the required input image dimensions for GoogLeNet.\nNow we’re to the crux of this post.\nOn\nLine 22\n, we call\ncv2.dnn.blobFromImage\nwhich, as stated in the previous section, will create a 4-dimensional\nblob\nfor use in our neural net.\nLet’s print the shape of our\nblob\nso we can analyze it in the terminal later (\nLine 23\n).\nNext, we’ll feed\nblob\nthrough GoogLeNet:\n# set the input to the pre-trained deep learning network and obtain\n# the output predicted probabilities for each of the 1,000 ImageNet\n# classes\nnet.setInput(blob)\npreds = net.forward()\n\n# sort the probabilities (in descending) order, grab the index of the\n# top predicted label, and draw it on the input image\nidx = np.argsort(preds[0])[::-1][0]\ntext = \"Label: {}, {:.2f}%\".format(classes[idx],\n\tpreds[0][idx] * 100)\ncv2.putText(image, text, (5, 25),  cv2.FONT_HERSHEY_SIMPLEX,\n\t0.7, (0, 0, 255), 2)\n\n# show the output image\ncv2.imshow(\"Image\", image)\ncv2.waitKey(0)\nIf you’re familiar with recent deep learning posts on this blog, the above lines should look familiar.\nWe feed the\nblob\nthrough the network (\nLines 28 and 29\n) and grab the predictions,\npreds\n.\nThen we sort\npreds\n(\nLine 33\n) with the most confident predictions at the front of the list, and generate a label text to display on the image. The label text consists of the class label and the prediction percentage value for the top prediction (\nLines 34 and 35\n).\nFrom there,  we write the label\ntext\nat the top of the\nimage\n(\nLines 36 and 37\n) followed by displaying the\nimage\non the screen and waiting for a keypress before moving on (\nLines 40 and 41\n).\nNow it’s time to use the\nplural form\nof the\nblobFromImage\nfunction.\nHere we’ll do (nearly) the same thing, except we’ll instead create and populate a list of\nimages\nfollowed by passing the list as a parameter to\nblobFromImages\n:\n# initialize the list of images we'll be passing through the network\nimages = []\n\n# loop over the input images (excluding the first one since we\n# already classified it), pre-process each image, and update the\n# `images` list\nfor p in imagePaths[1:]:\n\timage = cv2.imread(p)\n\timage = cv2.resize(image, (224, 224))\n\timages.append(image)\n\n# convert the images list into an OpenCV-compatible blob\nblob = cv2.dnn.blobFromImages(images, 1, (224, 224), (104, 117, 123))\nprint(\"Second Blob: {}\".format(blob.shape))\nFirst we initialize our\nimages\nlist (\nLine 44\n), and then, using the\nimagePaths\n, we read, resize, and append the\nimage\nto the list (\nLines 49-52\n).\nUsing list slicing, we’ve omitted the first image from\nimagePaths\non\nLine 49\n.\nFrom there, we pass the\nimages\ninto\ncv2.dnn.blobFromImages\nas the first parameter on\nLine 55\n. All other parameters to\ncv2.dnn.blobFromImages\nare identical to\ncv2.dnn.blobFromImage\nabove.\nFor analysis later we print\nblob.shape\non\nLine 56\n.\nWe’ll next pass the\nblob\nthrough GoogLeNet and write the class label and prediction at the top of each image:\n# set the input to our pre-trained network and obtain the output\n# class label predictions\nnet.setInput(blob)\npreds = net.forward()\n\n# loop over the input images\nfor (i, p) in enumerate(imagePaths[1:]):\n\t# load the image from disk\n\timage = cv2.imread(p)\n\n\t# find the top class label from the `preds` list and draw it on\n\t# the image\n\tidx = np.argsort(preds[i])[::-1][0]\n\ttext = \"Label: {}, {:.2f}%\".format(classes[idx],\n\t\tpreds[i][idx] * 100)\n\tcv2.putText(image, text, (5, 25),  cv2.FONT_HERSHEY_SIMPLEX,\n\t\t0.7, (0, 0, 255), 2)\n\n\t# display the output image\n\tcv2.imshow(\"Image\", image)\n\tcv2.waitKey(0)\nThe remaining code is essentially the same as above, only our\nfor\nloop now handles looping through each of the\nimagePaths\n(again, omitting the first one as we have already classified it).\nAnd that’s it! Let’s see the script in action in the next section.\nOpenCV blobfromImage and blobFromImages results\nNow we’ve reached the fun part.\nGo ahead and use the\n“Downloads”\nsection of this blog post to download the source code, example images, and pre-trained neural network. You will need the additional files in order to execute the code.\nFrom there, fire up a terminal and run the following command:\n$ python blob_from_images.py\nThe first terminal output is with respect to the first image found in the\nimages\nfolder where we apply the\ncv2.dnn.blobFromImage\nfunction:\nFirst Blob: (1, 3, 224, 224)\nThe resulting beer glass image is displayed on the screen:\nFigure 2:\nAn enticing beer has been labeled and recognized with high confidence by GoogLeNet. The blob dimensions resulting from\nblobFromImage\nare displayed in the terminal.\nThat full beer glass makes me thirsty. But before I enjoy a beer myself, I’ll explain why the shape of the blob is\n(1, 3, 224, 224)\n.\nThe resulting tuple has the following format:\n(num_images=1, num_channels=3, width=224, height=224)\nSince we’ve only processed\none\nimage, we only have\none\nentry in our\nblob\n. The channel count is three for BGR channels. And finally\n224×224\nis the spatial width and height for our input image.\nNext, let’s build a\nblob\nfrom the remaining four input images.\nThe second blob’s shape is:\nSecond Blob: (4, 3, 224, 224)\nSince this blob contains 4 images, the\nnum_images=4\n. The remaining dimensions are the same as the first, single image, blob.\nI’ve included a sample of correctly classified images below:\nFigure 3:\nMy keyboard has been correctly identified by GoogLeNet with a prediction confidence of 81%.\nFigure 4:\nI tested the pre-trained network on my computer monitor as well. Here we can see the input image is correctly classified using our Convolutional Neural Network.\nFigure 5:\nA NASA space shuttle is recognized with a prediction value of over 99% by our deep neural network.\nWhat's next? We recommend\nPyImageSearch University\n.\nCourse information:\n120+ total classes • 115+ hours of on-demand code walkthrough videos • Last updated: October 2026\n★★★★★\n4.84 (128 Ratings) • 16,000+ Students Enrolled\nI strongly believe that if you had the right teacher you could\nmaster\ncomputer vision and deep learning.\nDo you think learning computer vision and deep learning has to be time-consuming, overwhelming, and complicated? Or has to involve complex mathematics and equations? Or requires a degree in computer science?\nThat’s\nnot\nthe case.\nAll you need to master computer vision and deep learning is for someone to explain things to you in\nsimple, intuitive\nterms.\nAnd that’s exactly what I do\n. My mission is to change education and how complex Artificial Intelligence topics are taught.\nIf you're serious about learning computer vision, your next stop should be PyImageSearch University, the most comprehensive computer vision, deep learning, and OpenCV course online today. Here you’ll learn how to\nsuccessfully\nand\nconfidently\napply computer vision to your work, research, and projects. Join me in computer vision mastery.\nInside PyImageSearch University you'll find:\n✓\n120+ courses\non essential computer vision, deep learning, and OpenCV topics\n✓\n94+ Certificates\nof Completion\n✓\n115+ hours\nof on-demand video\n✓\nBrand new courses released\nregularly\n, ensuring you can keep up with state-of-the-art techniques\n✓\nPre-configured Jupyter Notebooks in Google Colab\n✓ Run all code examples in your web browser — works on Windows, macOS, and Linux (no dev environment configuration required!)\n✓ Access to\ncentralized code repos for\nall\n540+ tutorials\non PyImageSearch\n✓\nEasy one-click downloads\nfor code, datasets, pre-trained models, etc.\n✓\nAccess\non mobile, laptop, desktop, etc.\nClick here to join PyImageSearch University\nSummary\nIn today’s tutorial we examined OpenCV’s\nblobFromImage\nand\nblobFromImages\ndeep learning functions.\nThese methods are used to prepare input images for classification via pre-trained deep learning models.\nBoth\nblobFromImage\nand\nblobFromImages\nperform mean subtraction and scaling. We can also swap the Red and Blue channels of the image depending on channel ordering. Nearly all state-of-the-art deep learning models perform mean subtraction and scaling — the benefit here is that OpenCV makes these preprocessing tasks dead simple.\nIf you’re interested in studying deep learning in more detail, be sure to take a look at my brand new book,\nDeep Learning for Computer Vision with Python\n.\nInside the book you’ll discover:\nSuper practical walkthroughs\nthat present solutions to actual, real-world image classification problems, challenges, and competitions.\nDetailed, thorough experiments (with highly documented code) enabling you to\nreproduce state-of-the-art results.\nMy favorite “best practices”\nto improve network accuracy. These techniques alone will save you enough time to pay for the book multiple times over.\n..and much more!\nSound good?\nClick here to start your journey to deep learning mastery\n.\nOtherwise, be sure to enter your email address in the form below to be notified when future deep learning tutorials are published here on the PyImageSearch blog.\nSee you next week!\nDownload the Source Code and FREE 17-page Resource Guide\nEnter your email address below to get a .zip of the code and a\nFREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning.\nInside you'll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL!\nDownload the code!\nWebsite",
  "metadata": {
    "title": "Deep learning: How OpenCV's blobFromImage works - PyImageSearch",
    "description": null,
    "keywords": null,
    "author": "Adrian Rosebrock",
    "og:locale": "en_US",
    "og:type": "article",
    "og:title": "Deep learning: How OpenCV's blobFromImage works - PyImageSearch",
    "og:description": "Today’s blog post is inspired by a number of PyImageSearch readers who have commented on previous deep learning tutorials wanting to understand what exactly OpenCV’s blobFromImage function is doing under the hood. You see, to obtain (correct) predictions from deep…",
    "og:url": "https://pyimagesearch.com/2017/11/06/deep-learning-opencvs-blobfromimage-works/",
    "og:site_name": "PyImageSearch",
    "og:image": "https://pyimagesearch.com/wp-content/uploads/2017/11/blob_from_images_header.png",
    "og:image:width": "600",
    "og:image:height": "364",
    "og:image:type": "image/png",
    "twitter:label1": "Written by",
    "twitter:data1": "Adrian Rosebrock",
    "twitter:label2": "Est. reading time",
    "twitter:data2": "13 minutes",
    "article:published_time": "2017-11-06T15:00:11+00:00",
    "article:modified_time": "2023-02-20T10:38:07+00:00"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/4f1e783ead44/code/body-000.txt",
      "chars": 22,
      "language": "text"
    },
    {
      "file": "attachments/4f1e783ead44/code/body-001.txt",
      "chars": 463,
      "language": "text"
    },
    {
      "file": "attachments/4f1e783ead44/code/body-002.txt",
      "chars": 358,
      "language": "text"
    },
    {
      "file": "attachments/4f1e783ead44/code/body-003.txt",
      "chars": 569,
      "language": "text"
    },
    {
      "file": "attachments/4f1e783ead44/code/body-004.txt",
      "chars": 507,
      "language": "text"
    },
    {
      "file": "attachments/4f1e783ead44/code/body-005.txt",
      "chars": 601,
      "language": "text"
    },
    {
      "file": "attachments/4f1e783ead44/code/body-006.txt",
      "chars": 29,
      "language": "text"
    },
    {
      "file": "attachments/4f1e783ead44/code/body-007.txt",
      "chars": 29,
      "language": "text"
    },
    {
      "file": "attachments/4f1e783ead44/code/body-008.txt",
      "chars": 30,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://fast.wistia.com/embed/medias/r77x2pjd59/swatch",
      "bytes": 1954,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-29ed13cad4ec5443009f.img",
      "src": "https://fast.wistia.com/embed/medias/r77x2pjd59/swatch",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_header.png?lossy=2&strip=1&webp=1",
      "bytes": 9221,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-dd710e0b4e19df1db515.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_header.png?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2020/01/source-code-icon.png?lossy=2&strip=1&webp=1",
      "bytes": 884,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-0f8ec41d2103feb4399d.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2020/01/source-code-icon.png?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_mean_subtraction.jpg?lossy=2&strip=1&webp=1",
      "bytes": 23511,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-79fc0d5ed3b8456a5719.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_mean_subtraction.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/00d/00d17f8035a0d96ed31b6c7d4f68d407-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 218,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-d063a0c197dbbaa64276.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/00d/00d17f8035a0d96ed31b6c7d4f68d407-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "\\mu_R",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/029/02949639dff879b56cef44160bc985c7-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 209,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-0b452d4be5132711627c.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/029/02949639dff879b56cef44160bc985c7-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "\\mu_G",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/4b7/4b7a4c54b57c9297141ab648398f6dfc-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 218,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-938c2f6307cf809861ff.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/4b7/4b7a4c54b57c9297141ab648398f6dfc-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "\\mu_B",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/c9f/c9faf6ead2cd2c2187bd943488de1d0a-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 170,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-17dd254673c704ea23f9.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/c9f/c9faf6ead2cd2c2187bd943488de1d0a-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "\\mu",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/d11/d11ee9121f3d326ef4d5c81ff11bc5e6-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 308,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-bea5acaab533c5ac7217.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/d11/d11ee9121f3d326ef4d5c81ff11bc5e6-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "R = R - \\mu_R",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/ee5/ee51f3278d2531147a8ac04d00a4fedc-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 302,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-f6a27d4c50a60dc9aa2f.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/ee5/ee51f3278d2531147a8ac04d00a4fedc-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "G = G - \\mu_G",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/7a7/7a7638be15fc944e9cac16bbd923e834-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 307,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-a5a210a7dee18cc8cf07.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/7a7/7a7638be15fc944e9cac16bbd923e834-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "B = B - \\mu_B",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/a2a/a2ab7d71a0f07f388ff823293c147d21-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 160,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-36ba592d0e6e986ae661.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/a2a/a2ab7d71a0f07f388ff823293c147d21-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "\\sigma",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/a48/a48e51a51bd1c136db406951be811fc8-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 451,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-129e258b342849a4cc62.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/a48/a48e51a51bd1c136db406951be811fc8-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "R = (R - \\mu_R) / \\sigma",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/372/372f7e9f48777b8015c5160138e4dbc8-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 443,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-4853da6ceaabb0f998f6.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/372/372f7e9f48777b8015c5160138e4dbc8-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "G = (G - \\mu_G) / \\sigma",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/74a/74a24112c5ba30331b2a554f005eebb2-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 455,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-a6507ef15029e6dd49c9.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/74a/74a24112c5ba30331b2a554f005eebb2-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "B = (B - \\mu_B) / \\sigma",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/c45/c45775a317b5816f521570d2eb6ab787-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 190,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-8fb4b62dbaec16750dba.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/c45/c45775a317b5816f521570d2eb6ab787-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "\\sigma=1",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/latex/b66/b664c99b3bb452a9bf7ef10841e73fad-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "bytes": 220,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-003d92607425d6429329.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/latex/b66/b664c99b3bb452a9bf7ef10841e73fad-ffffff-000000-0.png?lossy=2&strip=1&webp=1",
      "alt": "1 / \\sigma",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_result01-300x207.jpg?lossy=2&strip=1&webp=1",
      "bytes": 9340,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-2f6765f2150c10385175.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_result01-300x207.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_result02-300x244.jpg?lossy=2&strip=1&webp=1",
      "bytes": 9010,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-a8111e092b009b689bb1.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_result02-300x244.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_result03-300x244.jpg?lossy=2&strip=1&webp=1",
      "bytes": 11633,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-abbc21a14fa0f58464e4.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_result03-300x244.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_result04-300x257.jpg?lossy=2&strip=1&webp=1",
      "bytes": 11447,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-b34a98f8da450be889a5.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2017/11/blob_from_images_result04-300x257.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://fast.wistia.com/embed/medias/kno0cmko2z/swatch",
      "bytes": 3143,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-8ec9834d54100244f57f.img",
      "src": "https://fast.wistia.com/embed/medias/kno0cmko2z/swatch",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2020/01/cta-source-guide-1.png?lossy=2&strip=1&webp=1",
      "bytes": 28126,
      "reused": false,
      "local_path": "attachments/4f1e783ead44/images/body-8cd5816cf73385d96fcd.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2020/01/cta-source-guide-1.png?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2017/11/blob_from_images_header.png",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2017/11/blob_from_images_mean_subtraction.jpg",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/deep-learning-computer-vision-python-book/",
      "label": "Deep Learning for Computer Vision with Python",
      "type": "a"
    },
    {
      "href": "https://docs.opencv.org/trunk/d6/d0f/group__dnn.html",
      "label": "official OpenCV documentation",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/2015/02/02/just-open-sourced-personal-imutils-package-series-opencv-convenience-functions/",
      "label": "imutils",
      "type": "a"
    },
    {
      "href": "https://github.com/jrosebr1/imutils",
      "label": "GitHub",
      "type": "a"
    },
    {
      "href": "https://pypi.python.org/pypi/imutils",
      "label": "Python Package Index",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/opencv-tutorials-resources-guides/",
      "label": "here",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2017/11/blob_from_images_result01.jpg",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2017/11/blob_from_images_result02.jpg",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2017/11/blob_from_images_result03.jpg",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2017/11/blob_from_images_result04.jpg",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend",
      "label": "PyImageSearch University",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:54:08Z",
  "source_url": "https://pyimagesearch.com/2017/11/06/deep-learning-opencvs-blobfromimage-works/",
  "papers": [],
  "actual_video_files": [
    {
      "local_path": "attachments/4f1e783ead44/videos/r77x2pjd59.mp4",
      "bytes": 375132864,
      "valid": true,
      "height": 1080,
      "width": 1920,
      "duration": "566.232333",
      "status": "ok"
    }
  ],
  "body_chars": 19013,
  "expected_body_images": 23,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/4f1e783ead44/pages/source.html",
  "local_html": "attachments/4f1e783ead44/pages/article.html",
  "body_base_path": "attachments/4f1e783ead44/pages/",
  "body_markdown_path": "attachments/4f1e783ead44/pages/article.md"
}