[opencv] Histogram-1: Find, draw and analyze

4_10_1_Histogram-1: Find, draw, analyze - OpenCV Chinese official documentation

- Use OpenCV and Numpy functions to find histograms - Use OpenCV and Matplotlib functions to draw histograms - You will see the following functions: cv.calcHist (), np.histogram (), etc.

  • Get an overview of the intensity distribution of the image from the histogram .

    It is a graph with pixel values ​​(not always a range from 0 to 255) on the X axis and the corresponding number of pixels in the image on the Y axis. (Statistics of pixel values)

    By viewing the histogram of an image, one can intuitively understand the contrast, brightness, intensity distribution, etc. of that image .

  • Finding a histogram: Two approaches: OpenCV and Numpy both have built-in functions for this.
  • Draw histogram: There are two methods, 1. Short method: using Matplotlib plotting function 2. Slightly longer method: using OpenCV plotting function
  • Find the histogram of certain areas of the image? Just create a mask image where you want to find the histogram as white, otherwise black. Then pass this as a mask.

content

theory

Find the histogram

1. Histogram calculation in OpenCV

2. Numpy histogram calculation

draw a histogram

1. Using Matplotlib

2. Using OpenCV

application of mask


 

theory

A histogram can be thought of as a graph or plot that gives an overview of the intensity distribution of an image .

It is a graph with pixel values ​​(not always a range from 0 to 255) on the X axis and the corresponding number of pixels in the image on the Y axis. (Statistics of pixel values)

It's just another way to understand images.

By looking at the histogram of an image, you can get an intuitive understanding of the contrast, brightness, intensity distribution, etc. of that image . Almost all image processing tools today offer a histogram function.

You can see the image and its histogram. (Remember that this histogram is drawn for a grayscale image, not a color image ).

  • The left area of ​​the histogram shows the number of darker pixels in the image, while the right area shows the number of bright pixels.
  • From the histogram, you can see that there are more dark areas than bright areas, while the number of midtones (pixel values ​​in the middle, such as around 127) is very small.

Find the histogram

Both OpenCV and Numpy have built-in functions for this. Before using these functions, we need to understand some terms related to histograms.

BINS (Regional Pixel Value Statistics) : The histogram above shows the number of pixels per pixel value, i.e. from 0 to 255. That is, you need 256 values ​​to display the histogram above. But what if instead of finding the number of pixels for all pixel values ​​individually, you find the number of pixels in an interval of pixel values? For example, you need to find the number of pixels between 0 and 15, then find the number of pixels between 16 and 31, ..., 240 and 255. Only 16 values ​​are required to represent the histogram. This is what is shown in the example about histograms in the OpenCV tutorial.

So all you have to do is divide the entire histogram into 16 subsections, and the value of each subsection is the sum of all the pixel counts in it. Each subsection is called a "BIN".

  • In the first case, the number of bins is 256 (one per pixel),
  • While in the second case, the number of bins is only 16.

BINS is represented by the **histSize** term in the OpenCV documentation.

DIMS : This is the number of parameters for which we collect data. In this case, we only collect data on one thing about the intensity value. So here is 1.

RANGE : This is the range of intensity values ​​you want to measure . Typically, it is [0,256], i.e. all intensity values.

1. Histogram calculation in OpenCV

So now we use the **cv.calcHist**() function to find the histogram. Let's get acquainted with the function and its parameters:

cv.calcHist(images,channels,mask,histSize,ranges [,hist [,accumulate]])

  1. images: It is a source image of type uint8 or float32 . It should be in square brackets, i.e. "[img]".
  2. channels: Also given in square brackets. It is the index of the channel where we compute the histogram.
    For example, if the input is a grayscale image, its value is [0] . For color images, you can pass [0], [1] or [2] to compute the histogram of the blue, green or red channel respectively .
  3. mask: Image mask. To find the histogram of the full image, specify "None".
    However, if you want to find the histogram of a specific area of ​​the image, you have to create a mask image for that and use it as a mask. (I'll show an example later.)
  4. histSize: This represents our BIN count. It needs to be enclosed in square brackets. For full size, we pass [256].
  5. ranges: This is our RANGE. Usually [0,256].

So let's start with an example image. Just load the image in grayscale and find its full histogram.

img = cv.imread('home.jpg',0)
hist = cv.calcHist([img],[0],None,[256],[0,256])

hist is a 256x1 array, each value corresponds to the number of pixels in this image with the corresponding pixel value.

2. Numpy histogram calculation

Numpy also provides you with a function **np.histogram**(). So instead of the calcHist**() function, you can try the following code:

hist,bins = np.histogram(img.ravel(),256,[0,256])

hist is the same as we calculated earlier. But the bin will have 257 elements, because Numpy calculates the bin's range as 0-0.99, 1-1.99, , 2-2.99etc. So the final range is 255-255.99. To indicate this, they also added 256 at the end. But we don't need 256. A maximum of 255 is sufficient.

  • In addition  , Numpy has another function **np.bincount**(), which is about 10 times faster than np.histogram(). So for a 1D histogram, you can better try it out. Don't forget to set minlength=256 in np.bincount. E.g,hist = np.bincount(img.ravel(),minlength = 256)

Note that  the OpenCV function is about 40 times faster than np.histogram(). Therefore, use OpenCV functions whenever possible.

Now we should draw the histogram, but how?

draw a histogram

There are two ways, 1. The short way: use the Matplotlib plotting function 2. The slightly longer way: use the OpenCV plotting function

1. Using Matplotlib

Matplotlib comes with a histogram plotting function: matplotlib.pyplot.hist() it directly finds the histogram and plots it. You don't need to use the calcHist**() or np.histogram() functions to find the histogram. See the code below:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('home.jpg',0)
plt.hist(img.ravel(),256,[0,256]); plt.show()

You will get the following result: 

Alternatively, you can use matplotlib's normal plots, which are great for BGR plots. To do this, you need to first find the histogram data. Try the following code:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('home.jpg')
color = ('b','g','r')
for i,col in enumerate(color):
    histr = cv.calcHist([img],[i],None,[256],[0,256])
    plt.plot(histr,color = col)
    plt.xlim([0,256])
plt.show()

result: 

You can draw from the image above that the blue color has some high value domain in the image (obviously this should be due to the sky)

2. Using OpenCV

Here you can adjust the values ​​of the histogram and its bins to look like the x,y coordinates so that you can plot it using the **cv.line**() or cv.polyline() functions to generate the same as the above the same image. The OpenCV-Python2 official example already provides this function. Check the code in examples/python/hist.py.

application of mask

We used cv.calcHist()to find the histogram of the whole image. What if you want to find the histogram of certain regions of the image?

Just create a mask image where the histogram you want to find is white , otherwise black. Then pass this as a mask.

img = cv.imread('home.jpg',0)
# create a mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv.bitwise_and(img,img,mask = mask)
# 计算掩码区域和非掩码区域的直方图
# 检查作为掩码的第三个参数
hist_full = cv.calcHist([img],[0],None,[256],[0,256])
hist_mask = cv.calcHist([img],[0],mask,[256],[0,256])
plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask,'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0,256])
plt.show()

View Results. In the histogram, the blue line represents the histogram of the full image, and the green line represents the histogram of the masked area.

Guess you like

Origin blog.csdn.net/dujuancao11/article/details/122437524