OpenCV-python 证件照换底 利用函数inRange及滑动条creatTrackbar分割
证件照换底HSV参考图片总是设定不准inRange的值。做一个利用滑条滑动直接看效果的吧
inRange
createTrackbar
显示BGR原图设置鼠标事件,点击需要换底色区域的HSV值
HSVvalue=cv2.getTrackbarPos('HSVvalue','image')#从滑块得到HSV上线减去的值。也可设置固定值'''1 判断H最小值减去HSVvalue设定值后小于0时,否则为02 判断H加HSVvalue后,最大值后不大于180,否则为1803 SV值相同处理,最小值不低于0否则为0 最大值不高于255否则为255'''cv2.setTrackbarPos('H_low','image', HSV[y,x][0]-HSVvalue if (HSV[y,x][0]-HSVvalue>0) else 0 )cv2.setTrackbarPos('H_high', 'image',HSV[y,x][0]+HSVvalue if (HSV[y,x][0]+HSVvalue<180) else 180)cv2.setTrackbarPos('S_Low', 'image', HSV[y,x][1]-HSVvalue if (HSV[y,x][1]-HSVvalue>0) else 0 )cv2.setTrackbarPos('S_high', 'image', HSV[y,x][1]+HSVvalue if (HSV[y,x][1]+HSVvalue<255) else 255)cv2.setTrackbarPos('V_low', 'image', HSV[y,x][2]-HSVvalue if (HSV[y,x][2]-HSVvalue>0) else 0)cv2.setTrackbarPos('V_high', 'image', HSV[y,x][2]+HSVvalue if (HSV[y,x][2]+HSVvalue<255) else 255)
设置createTrackbar的onchange事件,定义setHsvvalue,逐步调节HSV阈值
def setHsvvalue(userdata):HSVmin[0] =cv2.getTrackbarPos('H_low',winName)HSVmin[1] =cv2.getTrackbarPos('S_Low',winName)HSVmin[2] =cv2.getTrackbarPos('V_low',winName)HSVmax[0] =cv2.getTrackbarPos('H_high',winName)HSVmax[1] =cv2.getTrackbarPos('S_high',winName)HSVmax[2] =cv2.getTrackbarPos('V_high',winName)dst = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # BGR转HSVmask = cv2.inRange(dst, HSVmin, HSVmax) # 通过HSV的高低阈值,提取图像部分区域cv2.imshow('mask', mask)#主要用此maskopmask=cv2.bitwise_not(mask)cv2.imshow('opmask', opmask)#参考方便观察对比效果mask_dst=cv2.bitwise_and(image,image,mask=mask)cv2.imshow('mask_dst', mask_dst)opmask_dst=cv2.bitwise_and(image,image,mask=opmask)cv2.imshow('opmask_dst', opmask_dst)#参考方便观察对比效果cv2.setMouseCallback("opmask_dst",showimg)return mask #返回mask用于显示最终效果图
替换像素颜色
全部代码:
# -*- coding:utf-8 -*-'''读取证件照 转化为HSV色彩空间 并通过滑块调节HSV阈值,实时显示'''import cv2import numpy as npimage= cv2.imread('./data/zjz.jpg') # 读取图片image=cv2.resize(image,None,fx=0.5,fy=0.5)#可调整照片大小rows,cols,_ = image.shapeHSVmin = np.array([0, 0, 0])HSVmax = np.array([0, 0, 0])HSV= cv2.cvtColor(image,cv2.COLOR_BGR2HSV)HSVvalue=0winName='image''''鼠标点击响应事件1 获得当前鼠标点的HSV值2 初步获得颜色HSV设置阀值 改变滑块的值 高低各减去HSVvalue设置的值'''def getposHsv_setTP(event,x,y,flags,param):if event==cv2.EVENT_LBUTTONDOWN:print("HSV is",HSV[y,x])HSVvalue=cv2.getTrackbarPos('HSVvalue','image')cv2.setTrackbarPos('H_low','image', HSV[y,x][0]-HSVvalue if (HSV[y,x][0]-HSVvalue>0) else 0 )cv2.setTrackbarPos('H_high', 'image',HSV[y,x][0]+HSVvalue if (HSV[y,x][0]+HSVvalue<180) else 180)cv2.setTrackbarPos('S_low', 'image', HSV[y,x][1]-HSVvalue if (HSV[y,x][1]-HSVvalue>0) else 0 )cv2.setTrackbarPos('S_high', 'image', HSV[y,x][1]+HSVvalue if (HSV[y,x][1]+HSVvalue<255) else 255)cv2.setTrackbarPos('V_low', 'image', HSV[y,x][2]-HSVvalue if (HSV[y,x][2]-HSVvalue>0) else 0)cv2.setTrackbarPos('V_high', 'image', HSV[y,x][2]+HSVvalue if (HSV[y,x][2]+HSVvalue<255) else 255)#阈值调整好后点击鼠标显示图标 win系统 ctrl+S 可保存照片def showimg(event,x,y,flags,param):if event==cv2.EVENT_LBUTTONDOWN:mask=setHsvvalue(0)imageCopy=image.copy()imageCopy[mask==255]=(0,0,255) cv2.imshow('resultShow',imageCopy)#回调调节HSV阈值def setHsvvalue(userdata):HSVmin[0] =cv2.getTrackbarPos('H_low',winName)HSVmin[1] =cv2.getTrackbarPos('S_Low',winName)HSVmin[2] =cv2.getTrackbarPos('V_low',winName)HSVmax[0] =cv2.getTrackbarPos('H_high',winName)HSVmax[1] =cv2.getTrackbarPos('S_high',winName)HSVmax[2] =cv2.getTrackbarPos('V_high',winName)dst = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # BGR转HSVmask = cv2.inRange(dst, HSVmin, HSVmax) # 通过HSV的高低阈值,提取图像部分区域cv2.imshow('mask', mask)opmask=cv2.bitwise_not(mask)#辅助看效果cv2.imshow('opmask', opmask)mask_dst=cv2.bitwise_and(image,image,mask=mask)cv2.imshow('mask_dst', mask_dst)opmask_dst=cv2.bitwise_and(image,image,mask=opmask)#辅助看效果cv2.imshow('opmask_dst', opmask_dst)cv2.setMouseCallback("opmask_dst",showimg)return maskcv2.imshow("BGR", image) # 显示图片cv2.setMouseCallback("BGR",getposHsv_setTP)cv2.namedWindow(winName)cv2.createTrackbar('H_low', 'image', 0, 180, setHsvvalue) cv2.createTrackbar('H_high', 'image', 0, 180, setHsvvalue)cv2.createTrackbar('S_Low', 'image', 200, 255, setHsvvalue)cv2.createTrackbar('S_high', 'image', 255, 255, setHsvvalue)cv2.createTrackbar('V_low', 'image', 190, 255, setHsvvalue)cv2.createTrackbar('V_high', 'image', 244, 255, setHsvvalue)cv2.createTrackbar('HSVvalue', 'image', 10, 50,setHsvvalue)k = cv2.waitKey(0)if k in [27, ord('q')]:cv2.destroyAllWindows()
其中改背景色彩的方法,有平滑一点需求的话可先腐蚀再膨胀(开运算,用来消除mask内的白点)之后高斯滤波平滑处理mask
def showimg(event,x,y,flags,param):if event==cv2.EVENT_LBUTTONDOWN:mask=setHsvvalue(0)kernel = np.array(([0,1,0],[1,1,1],[0,1,0]),np.uint8)erosion = cv2.erode(mask,kernel,iterations = 1)#腐蚀mask =cv2.dilate(erosion,kernel,iterations = 1)#膨胀mask = cv2.GaussianBlur(mask,(3,3),0)#高斯mask_invs=cv2.bitwise_not(mask)img=cv2.bitwise_and(image,image,mask=mask_invs)bg=image.copy()#背景色图片制作bg[:rows,:cols,:]=[0,0,255]#设置为红色bgimg=cv2.bitwise_and(bg,bg,mask=mask)#背景设置为红色留出mask区域给头像img=cv2.add(img,bgimg)cv2.imshow('imgss', img)
此方法不是万能,比如照片底色和人物衣服比较接近,或者头发比较凌乱等情况效果就会比较差