直方图法确定阈值,实现图像白化,参考链接
https://blog.csdn.net/qq_43620967/article/details/121995903
#将素材中的人嵌入风景中,方法是
#视频的背景颜色(纯白色),关键在于确定阈值,第一次使用的方法是手动确定阈值,
#贴近人的边缘有噪声点 low_value = np.array([-1, 2, 110]) high_value = np.array([255, 50, 255])
#在老师的指导下,使用了一种更好的方法,直方图法确定阈值,改变图像大小为(920,500),还有一点需要注意的是把图像使用灰度图表示以后,
# 要与原图片做位运算操作,要重新转化为3通道图,这一次就没有噪声点了
import datetime
import time
#——————————————————————————————————————————————————————————————————————#
start_dt = datetime.datetime.now()
print("start_datetime:", start_dt)
time.sleep(2)
for i in range(10000):
i += 1
#——————————————————————————————————————————————————————————————————————#
import cv2
import numpy as np
# 计算灰度直方图
def calcGrayHist(grayimage):
# 灰度图像矩阵的高,宽
rows, cols = grayimage.shape
# 存储灰度直方图
grayHist = np.zeros([256], np.uint64)
for r in range(rows):
for c in range(cols):
grayHist[grayimage[r][c]] += 1
return grayHist
# 阈值分割:直方图技术法
def threshTwoPeaks(image):
#转换为灰度图
if len(image.shape) == 2:
gray = image
else:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 计算灰度直方图
histogram = calcGrayHist(gray)
# 寻找灰度直方图的最大峰值对应的灰度值
maxLoc = np.where(histogram == np.max(histogram))
# print(maxLoc)
firstPeak = maxLoc[0][0] #灰度值
# 寻找灰度直方图的第二个峰值对应的灰度值
measureDists = np.zeros([256], np.float32)
for k in range(256):
measureDists[k] = pow(k - firstPeak, 2) * histogram[k] #综合考虑 两峰距离与峰值
maxLoc2 = np.where(measureDists == np.max(measureDists))
secondPeak = maxLoc2[0][0]
print('双峰为:',firstPeak,secondPeak) # 181 26
# 找到两个峰值之间的最小值对应的灰度值,作为阈值
thresh = 0
if firstPeak > secondPeak: # 第一个峰值再第二个峰值的右侧
temp = histogram[int(secondPeak):int(firstPeak)]
minloc = np.where(temp == np.min(temp))
thresh = secondPeak + minloc[0][0] + 1
else: # 第一个峰值再第二个峰值的左侧
temp = histogram[int(firstPeak):int(secondPeak)]
minloc = np.where(temp == np.min(temp))
thresh = firstPeak + minloc[0][0] + 1
# 找到阈值之后进行阈值处理,得到二值图
threshImage_out = gray.copy()
# 大于阈值的都设置为255
threshImage_out[threshImage_out > thresh] = 255
threshImage_out[threshImage_out <= thresh] = 0
return thresh, threshImage_out
#路径--
Pep_video = "../data/People29.mp4"
Scene_video = "../data/BearScene.mp4"
Des_video = "../data/Destination.mp4"
#读取视频
Pep_Video = cv2.VideoCapture(Pep_video)
Scene_Video = cv2.VideoCapture(Scene_video)
#获取视频的频率 多少帧每秒
Fps_Pep = Pep_Video.get(cv2.CAP_PROP_FPS)
#设置视频写入的编码格式
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
#获取两个视频的宽度和高度
Pep_wid = int(Pep_Video.get(cv2.CAP_PROP_FRAME_WIDTH))
Pep_heit = int(Pep_Video.get(cv2.CAP_PROP_FRAME_HEIGHT))
# print(Pep_wid,Pep_heit)
#保存字幕后的视频
# videoWriter = cv2.VideoWriter(Des_video, fourcc, Fps_Pep, (920,500))
#把人和风景的视频都打开
frame = 0
thresh = 0
while True:
Pepret,Pepframe = Pep_Video.read()
Sceneret,Sceneframe = Scene_Video.read()
if Pepret == True and Sceneret == True :
frame += 1
Pepframe = cv2.resize(Pepframe,(920,500))
Sceneframe = cv2.resize(Sceneframe,(920,500))
img_gray = cv2.cvtColor(Pepframe, cv2.COLOR_BGR2GRAY)
if frame == 2: #发现第二帧的效果会比较好,第一帧有一些迷糊
thresh, img_sep = threshTwoPeaks(Pepframe)
print(thresh)
threshImage_out = img_gray.copy()
# 大于阈值的都设置为255
threshImage_out[threshImage_out > thresh] = 255
threshImage_out[threshImage_out <= thresh] = 0
#人是黑色的,背景是白色的
thresh3gate= cv2.cvtColor(threshImage_out, cv2.COLOR_GRAY2BGR)
#通过得到的三通道灰度图,按位运算,得到嵌入图
#得到人和白色背景
Peo_img = cv2.bitwise_or(thresh3gate,Pepframe)
#得到背景和白色人
thresh3gatenot = cv2.bitwise_not(thresh3gate)
#获取样本人的图片
samplePeo = cv2.bitwise_and(Peo_img,thresh3gatenot)
cv2.imshow("",samplePeo)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('../data/Peo_model.png', samplePeo)
Scene_img = cv2.bitwise_or(thresh3gatenot,Sceneframe)
#嵌入
embed_img = cv2.bitwise_and(Peo_img,Scene_img)
# videoWriter.write(embed_img)
print('Finish one frame')
else:
# videoWriter.release()
break
#——————————————————————————————————————————————————————————————————————#
end_dt = datetime.datetime.now()
print("end_datetime:", end_dt)
print("time cost:", (end_dt - start_dt).seconds, "s")
#——————————————————————————————————————————————————————————————————————#
#it costs 23s