[opencv] Histogram 4: Histogram back projection (use color histogram to find objects of interest)

4_10_4_Histogram-4: Histogram backprojection - OpenCV Chinese official documentation

Recap

Find Objects of Interest with Color Histogram: Calculate the probability of each pixel belonging to the region of interest and display it. The output produced at an appropriate threshold allows us to obtain only the region of interest (personal understanding adapts to the extraction of the region of interest with contrasting colors) .

 

 

content

theory

Algorithms in Numpy

Backprojection for OpenCV


theory

This was proposed by **Michael J. Swain** and **Dana H. Ballard** in their paper " Indexing by Color Histogram ".

What does it mean in simple words ?

  • It is used for image segmentation or to find objects of interest in an image .
  • It creates an image of the same size as the input image (but with only one channel), where each pixel corresponds to the probability that that pixel belongs to our object .
  • The output image will have more white values ​​in areas where there may be objects than the rest .
  • This is an intuitive explanation. Histogram backprojection is used in conjunction with the camshift algorithm, etc.

How can we do this ?

  • We create a histogram of the image containing the objects of our interest. Objects should fill the image as much as possible for better results.
  • And a color histogram is preferable to a grayscale histogram because the color of an object versus grayscale intensity is a good way to define an object.
  • We "back-project" this histogram onto the test image where the object needs to be found, in other words, we calculate the probability of each pixel belonging to the background and display it. The output produced at an appropriate threshold allows us to obtain only the background (here the background is the region of interest).

Algorithms in Numpy

1. First, we need to calculate the color histogram of the object we are looking for (let it be "M") and the image we want to search for (let it be "I") .

import numpy as np
import cv2 as cvfrom matplotlib import pyplot as plt
#roi是我们需要找到的对象或对象区域
roi = cv.imread('rose_red.png')
hsv = cv.cvtColor(roi,cv.COLOR_BGR2HSV)
#目标是我们搜索的图像
target = cv.imread('rose.png')
hsvt = cv.cvtColor(target,cv.COLOR_BGR2HSV)
# 使用calcHist查找直方图。也可以使用np.histogram2d完成
M = cv.calcHist([hsv],[0, 1], None, [180, 256], [0, 180, 0, 256] )
I = cv.calcHist([hsvt],[0, 1], None, [180, 256], [0, 180, 0, 256] )

2. Find the ratio . Then backproject R, i.e. use R as the palette and create a new image with each pixel as its corresponding target probability. i.e. B(x,y) = R[h(x,y),s(x,y)] where h is the hue and s is the saturation of the pixel at (x,y). After that, apply the conditions .

h,s,v = cv.split(hsvt)
B = R[h.ravel(),s.ravel()]
B = np.minimum(B,1)
B = B.reshape(hsvt.shape[:2])

3. Now apply convolution to the disk (region of interest) , B=D∗B, where D is the disk kernel.

disc = cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))
cv.filter2D(B,-1,disc,B)
B = np.uint8(B)
cv.normalize(B,B,0,255,cv.NORM_MINMAX)

4. Now the position of maximum intensity gives us the position of the object. If we expect an area in the image, thresholding a suitable value will give decent results.

ret,thresh = cv.threshold(B,50,255,0) 

That's it! !

Backprojection for OpenCV

  • OpenCV provides a built-in function **cv.calcBackProject**().
  • Its parameters are almost the same as the **cv.calcist**() function.
  • One of its parameters is the histogram, which is the histogram of the object, and we have to find it.
  • The object histogram should be normalized before being passed to the backproject function.
  • It returns probability images. Then we convolve the image with a disc kernel and apply a threshold.

Below is my code and result:

import numpy as np
import cv2 as cv
roi = cv.imread('rose_red.png')
hsv = cv.cvtColor(roi,cv.COLOR_BGR2HSV)
target = cv.imread('rose.png')
hsvt = cv.cvtColor(target,cv.COLOR_BGR2HSV)
# 计算对象的直方图
roihist = cv.calcHist([hsv],[0, 1], None, [180, 256], [0, 180, 0, 256] )
# 直方图归一化并利用反传算法
cv.normalize(roihist,roihist,0,255,cv.NORM_MINMAX)
dst = cv.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)
# 用圆盘进行卷积
disc = cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))
cv.filter2D(dst,-1,disc,dst)
# 应用阈值作与操作
ret,thresh = cv.threshold(dst,50,255,0)
thresh = cv.merge((thresh,thresh,thresh))
res = cv.bitwise_and(target,thresh)
res = np.vstack((target,thresh,res))
cv.imwrite('res.jpg',res)

Below is an example of what I've worked on. I am using the area inside the blue rectangle as a sample object and I want to extract the whole ground.

Guess you like

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