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:
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:
Another picture:
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:
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:
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
contrast is 1.0
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()
The 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.
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:
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
is to find an area similar to the template from the target image (the histogram is similar). The
result:
modify the value of ret, thresh = cv.threshold(dst, 200, 255, 0) to get better.