大体实现思路是根据双目成像原理,构建悬浮物移动模型,然后根据悬浮物在三维空间中的移动以及成像原理,将抠出的悬浮物图像贴到无杂质的水下双目图像中。1.首先最重要的是根据相机标定系数,确定世界坐标系(4×1)相机坐标系(4×1)、以及图像坐标系(3×1)的转换关系
由于是在matlab中软件标定,得到系数文件stereo.mat。大部分系数如相机外参(4×4)、双目相机内参和(3×4)、左目相机焦距、右目相机焦距、基线距均可直接得到,然而需要注意矩阵的转置与补1等关系。2.其次是先生成N个图像坐标系位置,便于控制悬浮物在成像范围内。然后根据坐标转换关系得到悬浮物在三维空间中的世界坐标,悬浮物的运动由构建的运动模型控制,其在左目与右目图像中的成像由成像原理得到。因此可以得到悬浮物在右目图像中的坐标。之后根据坐标系之间的转换关系将图像坐标转换至世界坐标系,并根据构建的悬浮物移动模型对下一帧的悬浮物坐标进行更新。每次将世界坐标系转换到相机坐标系,并计算z值,z值越大,表示越远,则图像越小,z值越小,表示越近,则图像越大,z值与图像大小保持反比关系。通过这种方式模拟现实场景中的近大远小效果。
3.最后记录所有双目帧中所有悬浮物的生成位置,生成mask掩码。为了方便,在将悬浮物贴到无杂质双目图像的过程中,同时以同样的方式将悬浮物贴到白色背景的等大图像中,从而便于计算掩码图。
from PIL import Image
import os
from cv2 import SimpleBlobDetector
import natsort
import numpy as np
import random
import cv2
from numpy.lib.arraysetops import _in1d_dispatcher
def gen_dataxiugai(N,In,Ex,img):#修改,希望根据随机生成的图像坐标得到世界坐标系下的坐标
""" init position and speed of each people """
height,width,c=img.shape#得到图像大小,建立越界约束
worldcords=[]
imagecords=[]
for i in range(N):
generateddata=np.array([[random.uniform(0,1)*width],[random.uniform(0,1)*height],[1]])
generateddata=[generateddata[0]/1,generateddata[1]/1,1]
# print("前一帧坐标")
# print(generateddata)#图像坐标
wordcor=Imgtoworld(In,Ex,generateddata)#根据图像坐标转换到世界坐标系下
x=wordcor[0]/wordcor[3]
y=wordcor[1]/wordcor[3]
z=wordcor[2]/wordcor[3]
theta = np.random.random(1) * 360 / (2 * np.pi)
v0 = 0.1
vx,vy,vz= v0 * np.cos(theta), v0 * np.sin(theta), v0 * np.tan(theta)#调节移动速度
vx,vy,vz=vx[0],vy[0],vz[0]
worldcords.append(np.array([x, y, z, vx, vy,vz]).T)
imagecords.append((generateddata[0],generateddata[1],generateddata[2]))
return worldcords,imagecords
def update1(data,In,Ex,N):#输入上一帧世界坐标计算下一帧图像坐标
imgcors=[]
print(data[:][0:3])
for d in range(N):
x=data[0][1]
data[d][0:3] += data[d][3:6]
if 60 >abs(data[d][0]) > 40:
data[d][3] *= -0.5
elif abs(data[d][0]) >= 60:
data[d][3] *= -1
else:
data[d][3] *=1
if 60 >abs(data[d][1]) > 40:
data[d][4] *= -0.5
elif abs(data[d][1]) >= 60:
data[d][4] *= -1
else:
data[d][4] *=1
if 60 >abs(data[d][2]) > 40:
data[d][5] *= -0.5
elif abs(data[d][2]) >= 60:
data[d][5] *= -1
else:
data[d][5] *=1
# data[d][3] *= random.randint (-2,-1) if abs(data[d][0]) > 40 else 1
# data[d][4] *= random.randint(-1,0) if abs(data[d][1]) > 40 else 1
# data[d][5] *= random.randint(-1,0) if abs(data[d][2]) > 40 else 1
x=data[d][0]
y=data[d][1]
z=data[d][2]
world=[[x],[y],[z],[1]]
imgcor=WorldtoImg(In,Ex,world)
imx=imgcor[0][0]/imgcor[2][0]
imy=imgcor[1][0]/imgcor[2][0]
imgcors.append(np.array([imx,imy]))
return imgcors
def Picture_Synthesis(mother_img,
son_img,
save_img,
coordinate):
"""
:param mother_img: 母图
:param son_img: 子图
:param save_img: 保存图片名
:param coordinate: 子图在母图的坐标
:return:
"""
#将图片赋值,方便后面的代码调用
M_Img = Image.open(mother_img)
S_Img = Image.open(son_img)
factor = 1#子图缩小的倍数1代表不变,2就代表原来的一半
#给图片指定色彩显示格式
M_Img = M_Img.convert("RGBA") # CMYK/RGBA 转换颜色格式(CMYK用于打印机的色彩,RGBA用于显示器的色彩)
S_Img = S_Img.convert("RGBA")
# 获取图片的尺寸
M_Img_w, M_Img_h = M_Img.size # 获取被放图片的大小(母图)
# print("母图尺寸:",M_Img.size)
S_Img_w, S_Img_h = S_Img.size # 获取小图的大小(子图)
# print("子图尺寸:",S_Img.size)
size_w = int(S_Img_w / factor)
size_h = int(S_Img_h / factor)
# 防止子图尺寸大于母图
if S_Img_w > size_w:
S_Img_w = size_w
if S_Img_h > size_h:
S_Img_h = size_h
# # 重新设置子图的尺寸
# icon = S_Img.resize((S_Img_w, S_Img_h), Image.ANTIALIAS)
icon = S_Img.resize((S_Img_w, S_Img_h), Image.ANTIALIAS)
w = int((M_Img_w - S_Img_w) / 2)
h = int((M_Img_h - S_Img_h) / 2)
r, g, b, a = icon.split()
img = cv2.cvtColor(np.asarray(icon),cv2.COLOR_RGBA2BGR)
img=img*0.8
img=img.astype(np.uint8)
icon = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
try:
(w, h)=coordinate
w= int (w)
h= int (h)
coordinate=(w, h)
if coordinate==None or coordinate=="":
coordinate=(w, h)
M_Img.paste(icon, coordinate, mask=a)
else:
M_Img.paste(icon, coordinate, mask=a)
except:
print("坐标指定出错 ")
# 保存图片
M_Img.save(save_img)
def WorldtoImg(In,Ex,Cor):#世界坐标系到tuxiang 坐标系
newCor=np.dot(Ex,Cor)
newCor=np.dot(In,newCor)
return newCor
def Worldtocamera(Ex,Cor):#世界坐标系到相机坐标系
newCor=np.dot(Ex,Cor)
return newCor
def imgtocamera(In,Cor):#图像坐标系到相机坐标系
zhuanhua_inv = np.linalg.pinv(In)
newCor=np.dot(zhuanhua_inv,Cor)
return newCor
def Imgtoworld(In,Ex,Cor):#(图像坐标系到世界坐标系
zhuanhua=np.dot(In,Ex)
zhuanhua_inv = np.linalg.pinv(zhuanhua)
newCor=np.dot(zhuanhua_inv,Cor)
return newCor
def cameratoimage(In,Cor):#相机坐标系到图像坐标系
newCor=np.dot(In,Cor)
return newCor
def rescale(img,z):#根据深度放大缩小,z 越大,月小
z=abs(z)
height,width,c=img.shape
print(z)
if(10000<height*width<1500):
z=z/1
elif(height*width<1500):#小悬浮物
z=z/3
else:
z=z*2.6
scale=100/z
fx=np.float(scale)
if(fx<0.03):
fx=0.03
if(fx!=1):
IMGA=cv2.resize(img,None,fx=fx, fy=fx, interpolation = cv2.INTER_CUBIC)
return IMGA
else:
return img
def init(In1,Ex,leftimage1,leftimage,sonfiles,rightimage,sonfolder,sonresizefolder,N,savel,saver,saveml0,savemr0,leftfiles):
worldcoraddvs,imgcors= gen_dataxiugai(N,In1,Ex,leftimage1)#根据随机生成的1个图像坐标得到世界坐标系下的1坐标
for i in range(len(sonfiles)):
sonimage=cv2.imread(sonfolder+'/'+sonfiles[i], cv2.IMREAD_UNCHANGED)
imgcor=imgcors[i]
worldcoraddv=worldcoraddvs[i]
wordcor=Imgtoworld(In1,Ex,imgcor)
wordcor=[ wordcor[0]/ wordcor[3],wordcor[1]/ wordcor[3],wordcor[2]/ wordcor[3],1]
imgcor=[imgcor[0],imgcor[1]]#2位图像坐标
x3=Worldtocamera(Ex,wordcor)#根据相机z resize图像
print(leftimage)
z=x3[2]
imgrightcor=WorldtoImg(In2,Ex,wordcor)#右目图像坐标系坐标
imgrightcor=[imgrightcor[0]/imgrightcor[2],imgrightcor[1]/imgrightcor[2]]
sonresize=rescale(sonimage,z)#返回放缩后的子图
newsonresizepath=sonresizefolder+'/'+sonfiles[i]
cv2.imwrite(sonresizefolder+'/'+sonfiles[i],sonresize)
cv2.imwrite(sonresizefolder2+'/'+str(z)+'_'+sonfiles[i],sonresize)
if(i==0):
Picture_Synthesis(mother_img=leftimage,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=savel,
coordinate=imgcor)
Picture_Synthesis(mother_img=rightimage,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=saver,
coordinate=imgrightcor)
Picture_Synthesis(mother_img=maskfolder+"/"+leftfiles[0],
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=saveml0,
coordinate=imgcor)
Picture_Synthesis(mother_img=maskfolder+"/"+leftfiles[0],
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=savemr0,
coordinate=imgrightcor)
else:
Picture_Synthesis(mother_img=savel,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=savel,
coordinate=imgcor)
Picture_Synthesis(mother_img=saver,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=saver,
coordinate=imgrightcor)
Picture_Synthesis(mother_img=saveml0,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=saveml0,
coordinate=imgcor)
Picture_Synthesis(mother_img=savemr0,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=savemr0,
coordinate=imgrightcor)
return worldcoraddvs
if __name__ == '__main__':
for k in range(52):
motherfolder="D:/zs/liefe/dataset/"+str(k+65)#母图的文件夹
sonfolder='D:/zs/zsxuanfuwukoutu/test/sonimg_black'#子图文件夹\
sonresizefolder='D:/zs/zsxuanfuwukoutu/test/sonimg_resize'
sonresizefolder2='D:/zs/zsxuanfuwukoutu/test/sonimg_resize2'
resultsfolder='D:/zs/liefe/dataset/'+str(k+65)+'/synthetize'
maskfolder='D:/zs/liefe/dataset/'+str(k+65)+'/mask'
leftfolder=motherfolder+'/left'
rightfolder=motherfolder+'/right'
leftfiles = os.listdir(leftfolder)
leftfiles = natsort.natsorted(leftfiles)
rightfiles = os.listdir(rightfolder)
rightfiles = natsort.natsorted(rightfiles)
sonfiles=os.listdir(sonfolder)
sonfiles = natsort.natsorted(sonfiles)
N=len(sonfiles)
#修改一下相机参数内容
#-------------------------------
Ex=np.array([[0.999913466711930,0.012427701940406,0.004314083055684,-45.437213269999994],
[-0.012426185378738,0.999922720468183,-3.781645688979914e-04,-0.076407119417775],
[-0.004318449381912,3.245242492851742e-04,0.999990622795508,0.905699234688221],
[0,0,0,1]])#相机外参
In1=np.array([[1.203553148440103e+03,0,6.396608693689266e+02,0],[0,1.206273889540051e+03,5.042248739033748e+02,0],[0,0,1,0]])#相机2内参
In2=np.array([[1.202927249456815e+03,0,6.159986634418301e+02,0],[0,1.204857250729929e+03,4.941098044508890e+02,0],[0,0,1,0]])#相机1内参
f1=np.array([1.202927249456815e+03,1.204857250729929e+03])#相机1焦距
f2=np.array([1.203553148440103e+03,1.206273889540051e+03])#相机2焦距
baseline=-45.437213269999994#基线距
#以上为相机参数---------------------------
#关于读图,左图右图与子图
leftimage=leftfolder+'/'+leftfiles[0]
#'D:/zs/zsxuanfuwukoutu/test/motherimg/left/2021-11-08-10_16_36-120.png'
rightimage=rightfolder+'/'+rightfiles[0]#'D:/zs/zsxuanfuwukoutu/test/motherimg/right/2021-11-08-10_16_36-120.png'
savel0=resultsfolder+'/left'+'/l'+leftfiles[0]
saver0=resultsfolder+'/right'+'/r'+rightfiles[0]
saveml0='D:/zs/liefe/dataset/'+str(k+65)+'/mask/left'+'/l'+leftfiles[0]
savemr0='D:/zs/liefe/dataset/'+str(k+65)+'/mask/right'+'/r'+rightfiles[0]
leftimage1=cv2.imread(leftimage)
height,width,c=leftimage1.shape#得到图像大小,建立越界约束
for j in range(len(leftfiles)):
img = Image.new('RGB', (width,height), (255, 255, 255))
img.save(maskfolder+"/"+leftfiles[j])
worldcoraddvs=init(In1,Ex,leftimage1,leftimage,sonfiles,rightimage,sonfolder,sonresizefolder,N,savel0,saver0,saveml0,savemr0,leftfiles)
for j in range(len(leftfiles)-1):
for i in range(len(sonfiles)):
leftimage = leftfiles[j+1]
rightimage= rightfiles[j+1]
son_image=sonfiles[i]
sonimage=cv2.imread(sonfolder+'/'+son_image, cv2.IMREAD_UNCHANGED)
#更新下一帧------------------------
saveli=resultsfolder+'/left'+'/l'+leftfiles[j+1]
saveri=resultsfolder+'/right'+'/r'+rightfiles[j+1]
savemli="D:/zs/liefe/dataset/"+str(k+65)+"/mask/left"+"/l"+leftfiles[j+1]
savemri="D:/zs/liefe/dataset/"+str(k+65)+"/mask/right/"+"/r"+rightfiles[j+1]
print(leftfolder+'/'+leftimage)
#给左图第二帧贴子图
newimage=update1(worldcoraddvs,In1,Ex,N)#更新得到新的图像坐标
newimage1=[newimage[i][0],newimage[i][1],1]
newworldcor=Imgtoworld(In1,Ex,newimage1)#新的左目世界坐标
newworldcor=[ newworldcor[0]/ newworldcor[3],newworldcor[1]/ newworldcor[3],newworldcor[2]/ newworldcor[3],1]
newright_imgcor=WorldtoImg(In2,Ex,newworldcor)#新的右目图像坐标
newright_imgcor=[newright_imgcor[0]/newright_imgcor[2],newright_imgcor[1]/newright_imgcor[2]]
x4= Worldtocamera(Ex,newworldcor)#世界坐标系到相机坐标系#根据相机z resize图像
z2=x4[2]
sonresize2=rescale(sonimage,z2)
cv2.imwrite(sonresizefolder2+'/'+str(z2)+sonfiles[i],sonresize2)
cv2.imwrite(sonresizefolder+'/'+sonfiles[i],sonresize2)
if(i==0):
Picture_Synthesis(mother_img=leftfolder+'/'+leftimage,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=saveli,
coordinate=newimage[i])
Picture_Synthesis(mother_img=rightfolder+'/'+rightimage,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=saveri,
coordinate=newright_imgcor)
Picture_Synthesis(mother_img=maskfolder+'/'+leftimage,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=savemli,
coordinate=newimage[i])
Picture_Synthesis(mother_img=maskfolder+'/'+rightimage,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=savemri,
coordinate=newright_imgcor)
else:
Picture_Synthesis(mother_img=saveli,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=saveli,
coordinate=newimage[i])
Picture_Synthesis(mother_img=saveri,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=saveri,
coordinate=newright_imgcor)
Picture_Synthesis(mother_img=savemli,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=savemli,
coordinate=newimage[i])
Picture_Synthesis(mother_img=savemri,
son_img=sonresizefolder+'/'+sonfiles[i],
save_img=savemri,
coordinate=newright_imgcor)
版权声明:本文为zhangshan0620原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。