直方图反向投影

其实质是图像分割,即是寻找一副图像的感兴趣物体

算法如下:
1、 分别计算原图和roi图的H,S 通道的直方图
2、 计算比率 R=roiHist/Hist
3、 反向投影
B(X,Y)=R(h(x,y),s(x,y))
B(x,y)=min[B(x,y),1]
h,s 是原图的h和s 通道
4、 对B 均值滤波
5、 用得到的B(mask) 与原图与操作得到感兴趣物体
下面是按照上面步骤进行直方图反向投影和利用opencv现有函数calcBackProject两种方式来进行。
Example:
如图,我们想得到蓝色屋顶区域。
这里写图片描述
python 代码:

# -*- coding: utf-8 -*-
#直方图反向投影
import cv2
import numpy as np
im1=cv2.imread(r'C:\Users\Y\Desktop\12.jpg')
im1 = cv2.bilateralFilter(im1, 13, 70, 50)
box_roi=cv2.selectROI("roi",im1)
roi_im=im1[box_roi[1]:box_roi[1]+box_roi[3],box_roi[0]:box_roi[0]+box_roi[2],:]
hsv1=cv2.cvtColor(im1,cv2.COLOR_BGR2HSV)
hsv2=cv2.cvtColor(roi_im,cv2.COLOR_BGR2HSV)
hist1=cv2.calcHist([hsv1],[0,1],None,[180,256],[0,180,0,256])#h 范围为0-180,s范围0-360
hist2=cv2.calcHist([hsv2],[0,1],None,[180,256],[0,180,0,256])
#######计算比值
R=hist2/(hist1+1)#加1 是为了避免除0
h,s,v=cv2.split(hsv1)
B=R[h.ravel(),s.ravel()]
B=np.minimum(B,1)
B=B.reshape(hsv1.shape[:2])*255
##
structure =cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
B=cv2.filter2D(B,-1,structure) #-1代表卷积padding
B=np.uint8(B)
ret,thresh = cv2.threshold(B,50,255,0)
thresh = cv2.merge((thresh,thresh,thresh))
res = cv2.bitwise_and(im1,thresh)
cv2.imwrite(r'C:\Users\Y\Desktop\res.jpg',res)
##########利用 cv2.calcBackProject
dst=cv2.calcBackProject([hsv1],[0,1],hist2,[0,180,0,256],1)#hist2是roi的直方图,将roi的直方图投影到原图的hsv空间得到mask
disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
cv2.filter2D(dst,-1,disc,dst)
out=cv2.merge([dst,dst,dst])&im1
cv2.imwrite(r'C:\Users\Y\Desktop\res1.jpg',out)

效果图
按照上面写的算法步骤得到的result
这里写图片描述
opencv 自带函数效果
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_15642411/article/details/80733582