opencv learning nine: image histogram, histogram application, histogram back projection

1. Image histogram

1.1 numpy implementation

Function: hist (data source, pixel level)
Data source: image, must be a one-dimensional array
Pixel level: generally 256, which means [0-255]
np.raval() can realize multi-dimensional array to one-dimensional.

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

def plot_demo(image):
    plt.hist(image.ravel(),256,[0,256])# image.ravel()将图像展开,256为bins数量,[0, 256]为范围
    # plt.hist(image.ravel(),256)#两种写法都对
    plt.show()
    
src = cv.imread("C:/Users/lenovo/Desktop/opencv/daima/banknum/template-matching-ocr/images/lena.jpg")  #读取图片位置
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
plot_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

Run screenshot:
Insert picture description here

1.2 OpenCV implementation

hist=cv2.calcHist(images,channels,mask,histsize,ranges,accumulate)
hist: histogram
images: original image, format [src], need to be enclosed in
square brackets channels: channel, gray direct [0], BGR corresponds [0], [1], [2]
mask: mask image. If a graph is large, the histogram of part of the graph needs to be calculated and a mask is required.
histsize: The number of BINS, which needs to be enclosed in square brackets. Generally [256]
ranges: pixel value range, generally [0,255]
accumulate: accumulate identification. Optional parameter, default false, set to true to calculate the histogram of several pictures.

def image_hist(image):
    color = ('blue', 'green', 'red')
    for i, color in enumerate(color):
 
        # 计算出直方图,calcHist(images, channels, mask, histSize(有多少个bin), ranges[, hist[, accumulate]]) -> hist
        # hist 是一个 256x1 的数组,每一个值代表了与该灰度值对应的像素点数目。
 
        hist = cv.calcHist(image, [i], None, [256], [0, 256])
        print(hist.shape)
        plt.plot(hist, color=color)
        plt.xlim([0, 256])
    plt.show()

Run screenshot:
Insert picture description here
Another picture:
Insert picture description here

2. Image histogram application

2.1 Global histogram equalization

The histogram equalization is based on the gray graph. The
principle is shown in the basic link mentioned above.
Effect: the contrast graph is enhanced

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

def equalHist_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    dst = cv.equalizeHist(gray)
    cv.imshow("equalHist_demo", dst)

src = cv.imread("C:/Users/lenovo/Desktop/opencv/daima/banknum/template-matching-ocr/images/lena.jpg")  #读取图片位置
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)

equalHist_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

Run screenshot:
Insert picture description here

2.2 Partial histogram equalization

Locally adaptive image histogram equalization
Adaptive histogram equalization (AHE) is a computer image processing technology used to improve the contrast of an image. Different from the ordinary histogram equalization algorithm, the AHE algorithm changes the image contrast by calculating the local histogram of the image and then redistributing the brightness. Therefore, the algorithm is more suitable for improving the local contrast of the image and obtaining more image details.

However, AHE has the problem of excessively amplifying the noise in the same area of ​​the image. Another adaptive histogram equalization algorithm, the limited contrast histogram equalization (CLAHE) algorithm, can limit this unfavorable amplification.

cv2.createCLAHE(clipLimit=5.0, tileGridSize=(8, 8))
The meaning of the first parameter is that the small part of the histogram larger than clipLimit will be clipped and evenly distributed to the entire image; the meaning of the second parameter Is the size of the divided small area. The general value of clipLimit is set to 40. If it is customized, the larger the value, the more obvious the effect of homogenization. The closer the value is to zero, it is no different from the original image. The
schematic diagram:
Insert picture description here

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

#局部均衡化
def clahe_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    clahe = cv.createCLAHE(clipLimit=5.0, tileGridSize=(8, 8)) #1.0 3.0 5.0对比度会增加
    dst = clahe.apply(gray)
    cv.imshow("clahe_demo", dst)

src = cv.imread("C:/Users/lenovo/Desktop/opencv/daima/banknum/template-matching-ocr/images/lena.jpg")  #读取图片位置
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)

clahe_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

Run screenshot: the effect when the
contrast clipLimit is set to 1 3 5 and the
Insert picture description herecontrast is 1.0
Insert picture description here

2.3 Comparison of histograms

Calculate the histograms H1 and H2 from the two input images, normalize them to the same scale space, and then calculate the distance between H1 and H2 to obtain the similarity of the two histograms and compare the similarity of the images themselves .
Histogram comparison function

cv2.compareHist(H1, H2, method)
where:

H1, H2 are the histogram
methods of the images to be compared -comparison method
comparison method (method)

The correlation comparison (method=cv.HISTCMP_CORREL) value is larger, the correlation degree is higher, the maximum value is 1, the minimum value is 0
Chi-square comparison (method=cv.HISTCMP_CHISQR value is smaller, the correlation degree is higher, the maximum value is no upper Boundary, minimum value 0
Bhattacharyya distance comparison (method=cv.HISTCMP_BHATTACHARYYA) The smaller the value, the higher the correlation, the maximum value is 1, the minimum value is 0

import cv2 as cv
import numpy as np


#rgb直方图
def create_rgb_hist(image):
    h, w, c = image.shape
    rgbHist = np.zeros([16*16*16, 1], np.float32)#直方图初始化
    bsize = 256 / 16
    for row in range(h):
        for col in range(w):
            b = image[row, col, 0]
            g = image[row, col, 1]
            r = image[row, col, 2]
            index = np.int(b/bsize)*16*16 + np.int(g/bsize)*16 + np.int(r/bsize)
            rgbHist[np.int(index), 0] = rgbHist[np.int(index), 0] + 1#出现了就加1
    return rgbHist
 #比较函数
def hist_compare(image1, image2):
    hist1 = create_rgb_hist(image1)
    hist2 = create_rgb_hist(image2)
    match1 = cv.compareHist(hist1, hist2, cv.HISTCMP_BHATTACHARYYA)#比较方法1,越小越相似
    match2 = cv.compareHist(hist1, hist2, cv.HISTCMP_CORREL)#相关性越大越相似
    match3 = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR)#卡方越大约不相似
    print("巴氏距离: %s, 相关性: %s, 卡方: %s"%(match1, match2, match3))

print("--------- Hello Python ---------")
src1 = cv.imread("renwu1.jpg")
src2 = cv.imread("renwu.jpg")
src1=cv.resize(src1,None,fx=0.5,fy=0.5)
src2=cv.resize(src2,None,fx=0.5,fy=0.5)
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src1)
cv.imshow("image2", src2)
hist_compare(src1, src2)
cv.waitKey(0)
cv.destroyAllWindows()


image1 = cv.imread("C:/Users/lenovo/Desktop/opencv/daima/banknum/template-matching-ocr/images/lena.jpg")
image2 = cv.imread("C:/Users/lenovo/Desktop/opencv/daima/banknum/template-matching-ocr/images/quzao.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("image1", image1)
cv.imshow("image2", image2)
hist_compare(image1, image2)
cv.waitKey(0)
cv.destroyAllWindows()

Insert picture description hereThe greater the Bhattacharyya distance, the greater the picture difference

3. Histogram back projection

The histogram back projection method finds the corresponding pixel distribution area in the image through the given histogram information. Opencv provides two algorithms, one is pixel-based and the other is block-based.
Insert picture description here
2D histogram establishment The
histogram is based on 2D, first calculate the 2D histogram to establish.

It is simple and convenient to use the function cv2.calcHist() to calculate the histogram. If you want to draw a color histogram, you first need to convert the color space of the image from BGR to HSV. (Remember, to calculate a two-dimensional histogram, you need to convert from BGR to HSV). To calculate the 2D histogram, the parameters of the function need to be modified as follows:
• channels=[0, 1] Because we need to process the H and S channels at the same time.
• bins=[180, 256] The H channel is 180, and the S channel is 256. If you write other values ​​(less than 180,256), it means that the channel is merged.
• range=[0, 180, 0, 256] The value range of H is 0 to 180, and the value range of S is 0 to 256.
hist = cv2.calcHist([image], [0, 1], None, [32, 32], [0, 180, 0, 256])

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
#直方图的建立
def hist2d_demo(image):
    hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
    hist = cv.calcHist([image], [0, 1], None, [180, 256], [0, 180, 0, 256])
    #cv.imshow("hist2d", hist)
    plt.imshow(hist, interpolation='nearest')#nearest邻近点插值
    plt.title("2D Histogram")
    plt.show()

src = cv.imread("C:/Users/lenovo/Desktop/opencv/daima/banknum/template-matching-ocr/images/lena.jpg")  #读取图片位置
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
hist2d_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

Run screenshot:
Insert picture description here

3.2 Histogram back projection

It's a bit vague for the time being, follow up

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


def back_projection_demo():
    # ROI区域
    roi= cv.imread("head.png")
    #roi=cv.resize(roi,None,fx=0.5,fy=0.5)
    #目标搜索区域
    target = cv.imread("renwu.jpg")
    target= cv.resize(target, None, fx=0.2, fy=0.2)
    roi_hsv = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
    target_hsv = cv.cvtColor(target, cv.COLOR_BGR2HSV)

    # show images
    cv.imshow("roi", roi)
    #cv.imshow("target", target)

    roiHist = cv.calcHist([roi_hsv], [0, 1], None, [180,256], [0, 180, 0, 256])#2D直方图
    cv.normalize(roiHist, roiHist, 0, 255, cv.NORM_MINMAX)#归一化到0-255
    dst = cv.calcBackProject([target_hsv], [0, 1], roiHist, [0, 180, 0, 256], 1)
    #cv.imshow("backProjectionDemo", dst)

    # 此处卷积可以把分散的点连在一起
    disc = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
    dst = cv.filter2D(dst, -1, disc)
    # threshold and binary AND
    ret, thresh = cv.threshold(dst, 200, 255, 0)
    # 别忘了是三通道图像,因此这里使用 merge 变成 3 通道
    thresh = cv.merge((thresh, thresh, thresh))
    # 按位操作
    res = cv.bitwise_and(target, thresh)
    res = np.hstack((target, thresh, res))
    cv.imshow('res',res)
    #cv.imwrite('res.jpg', res)

back_projection_demo()
cv.waitKey(0)

cv.destroyAllWindows()

The original template ROI
Insert picture description hereis to find an area similar to the template from the target image (the histogram is similar). The
result:
Insert picture description heremodify the value of ret, thresh = cv.threshold(dst, 200, 255, 0) to get better.

Guess you like

Origin blog.csdn.net/weixin_44145452/article/details/112484138