def test_simple(self): img = self.get_sample('stitching/a1.png') finder= cv.ORB.create() imgFea = cv.detail.computeImageFeatures2(finder,img) self.assertIsNotNone(imgFea) matcher = cv.detail_BestOf2NearestMatcher(False, 0.3) self.assertIsNotNone(matcher) matcher = cv.detail_AffineBestOf2NearestMatcher(False, False, 0.3) self.assertIsNotNone(matcher) matcher = cv.detail_BestOf2NearestRangeMatcher(2, False, 0.3) self.assertIsNotNone(matcher) estimator = cv.detail_AffineBasedEstimator() self.assertIsNotNone(estimator) estimator = cv.detail_HomographyBasedEstimator() self.assertIsNotNone(estimator) adjuster = cv.detail_BundleAdjusterReproj() self.assertIsNotNone(adjuster) adjuster = cv.detail_BundleAdjusterRay() self.assertIsNotNone(adjuster) adjuster = cv.detail_BundleAdjusterAffinePartial() self.assertIsNotNone(adjuster) adjuster = cv.detail_NoBundleAdjuster() self.assertIsNotNone(adjuster) compensator=cv.detail.ExposureCompensator_createDefault(cv.detail.ExposureCompensator_NO) self.assertIsNotNone(compensator) compensator=cv.detail.ExposureCompensator_createDefault(cv.detail.ExposureCompensator_GAIN) self.assertIsNotNone(compensator) compensator=cv.detail.ExposureCompensator_createDefault(cv.detail.ExposureCompensator_GAIN_BLOCKS) self.assertIsNotNone(compensator) seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_NO) self.assertIsNotNone(seam_finder) seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_NO) self.assertIsNotNone(seam_finder) seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM) self.assertIsNotNone(seam_finder) seam_finder = cv.detail_GraphCutSeamFinder("COST_COLOR") self.assertIsNotNone(seam_finder) seam_finder = cv.detail_GraphCutSeamFinder("COST_COLOR_GRAD") self.assertIsNotNone(seam_finder) seam_finder = cv.detail_DpSeamFinder("COLOR") self.assertIsNotNone(seam_finder) seam_finder = cv.detail_DpSeamFinder("COLOR_GRAD") self.assertIsNotNone(seam_finder) blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO) self.assertIsNotNone(blender) blender = cv.detail.Blender_createDefault(cv.detail.Blender_FEATHER) self.assertIsNotNone(blender) blender = cv.detail.Blender_createDefault(cv.detail.Blender_MULTI_BAND) self.assertIsNotNone(blender) timelapser = cv.detail.Timelapser_createDefault(cv.detail.Timelapser_AS_IS); self.assertIsNotNone(timelapser) timelapser = cv.detail.Timelapser_createDefault(cv.detail.Timelapser_CROP); self.assertIsNotNone(timelapser)
def bundle_adjustment_cost_function_check(ba_cost_func): adjuster = None if ba_cost_func == "reproj": adjuster = cv2.detail_BundleAdjusterReproj() elif ba_cost_func == "ray": adjuster = cv2.detail_BundleAdjusterRay() elif ba_cost_func == "affine": adjuster = cv2.detail_BundleAdjusterAffinePartial() elif ba_cost_func == "no": adjuster = cv2.detail_NoBundleAdjuster() else: print("Unknown bundle adjustment cost function: ", ba_cost_func) exit() return adjuster
def main(): args = parser.parse_args() img_names=args.img_names print(img_names) preview = args.preview try_cuda = args.try_cuda work_megapix = args.work_megapix seam_megapix = args.seam_megapix compose_megapix = args.compose_megapix conf_thresh = args.conf_thresh features_type = args.features matcher_type = args.matcher estimator_type = args.estimator ba_cost_func = args.ba ba_refine_mask = args.ba_refine_mask wave_correct = args.wave_correct if wave_correct=='no': do_wave_correct= False else: do_wave_correct=True if args.save_graph is None: save_graph = False else: save_graph =True save_graph_to = args.save_graph warp_type = args.warp if args.expos_comp=='no': expos_comp_type = cv.detail.ExposureCompensator_NO elif args.expos_comp=='gain': expos_comp_type = cv.detail.ExposureCompensator_GAIN elif args.expos_comp=='gain_blocks': expos_comp_type = cv.detail.ExposureCompensator_GAIN_BLOCKS elif args.expos_comp=='channel': expos_comp_type = cv.detail.ExposureCompensator_CHANNELS elif args.expos_comp=='channel_blocks': expos_comp_type = cv.detail.ExposureCompensator_CHANNELS_BLOCKS else: print("Bad exposure compensation method") exit() expos_comp_nr_feeds = args.expos_comp_nr_feeds expos_comp_nr_filtering = args.expos_comp_nr_filtering expos_comp_block_size = args.expos_comp_block_size match_conf = args.match_conf seam_find_type = args.seam blend_type = args.blend blend_strength = args.blend_strength result_name = args.output if args.timelapse is not None: timelapse = True if args.timelapse=="as_is": timelapse_type = cv.detail.Timelapser_AS_IS elif args.timelapse=="crop": timelapse_type = cv.detail.Timelapser_CROP else: print("Bad timelapse method") exit() else: timelapse= False range_width = args.rangewidth if features_type=='orb': finder= cv.ORB.create() elif features_type=='surf': finder= cv.xfeatures2d_SURF.create() elif features_type=='sift': finder= cv.xfeatures2d_SIFT.create() else: print ("Unknown descriptor type") exit() seam_work_aspect = 1 full_img_sizes=[] features=[] images=[] is_work_scale_set = False is_seam_scale_set = False is_compose_scale_set = False; for name in img_names: full_img = cv.imread(cv.samples.findFile(name)) if full_img is None: print("Cannot read image ", name) exit() full_img_sizes.append((full_img.shape[1],full_img.shape[0])) if work_megapix < 0: img = full_img work_scale = 1 is_work_scale_set = True else: if is_work_scale_set is False: work_scale = min(1.0, np.sqrt(work_megapix * 1e6 / (full_img.shape[0]*full_img.shape[1]))) is_work_scale_set = True img = cv.resize(src=full_img, dsize=None, fx=work_scale, fy=work_scale, interpolation=cv.INTER_LINEAR_EXACT) if is_seam_scale_set is False: seam_scale = min(1.0, np.sqrt(seam_megapix * 1e6 / (full_img.shape[0]*full_img.shape[1]))) seam_work_aspect = seam_scale / work_scale is_seam_scale_set = True imgFea= cv.detail.computeImageFeatures2(finder,img) features.append(imgFea) img = cv.resize(src=full_img, dsize=None, fx=seam_scale, fy=seam_scale, interpolation=cv.INTER_LINEAR_EXACT) images.append(img) if matcher_type== "affine": matcher = cv.detail_AffineBestOf2NearestMatcher(False, try_cuda, match_conf) elif range_width==-1: matcher = cv.detail.BestOf2NearestMatcher_create(try_cuda, match_conf) else: matcher = cv.detail.BestOf2NearestRangeMatcher_create(range_width, try_cuda, match_conf) p=matcher.apply2(features) matcher.collectGarbage() if save_graph: f = open(save_graph_to,"w") f.write(cv.detail.matchesGraphAsString(img_names, p, conf_thresh)) f.close() indices=cv.detail.leaveBiggestComponent(features,p,0.3) img_subset =[] img_names_subset=[] full_img_sizes_subset=[] num_images=len(indices) for i in range(len(indices)): img_names_subset.append(img_names[indices[i,0]]) img_subset.append(images[indices[i,0]]) full_img_sizes_subset.append(full_img_sizes[indices[i,0]]) images = img_subset; img_names = img_names_subset; full_img_sizes = full_img_sizes_subset; num_images = len(img_names) if num_images < 2: print("Need more images") exit() if estimator_type == "affine": estimator = cv.detail_AffineBasedEstimator() else: estimator = cv.detail_HomographyBasedEstimator() b, cameras =estimator.apply(features,p,None) if not b: print("Homography estimation failed.") exit() for cam in cameras: cam.R=cam.R.astype(np.float32) if ba_cost_func == "reproj": adjuster = cv.detail_BundleAdjusterReproj() elif ba_cost_func == "ray": adjuster = cv.detail_BundleAdjusterRay() elif ba_cost_func == "affine": adjuster = cv.detail_BundleAdjusterAffinePartial() elif ba_cost_func == "no": adjuster = cv.detail_NoBundleAdjuster() else: print( "Unknown bundle adjustment cost function: ", ba_cost_func ) exit() adjuster.setConfThresh(1) refine_mask=np.zeros((3,3),np.uint8) if ba_refine_mask[0] == 'x': refine_mask[0,0] = 1 if ba_refine_mask[1] == 'x': refine_mask[0,1] = 1 if ba_refine_mask[2] == 'x': refine_mask[0,2] = 1 if ba_refine_mask[3] == 'x': refine_mask[1,1] = 1 if ba_refine_mask[4] == 'x': refine_mask[1,2] = 1 adjuster.setRefinementMask(refine_mask) b,cameras = adjuster.apply(features,p,cameras) if not b: print("Camera parameters adjusting failed.") exit() focals=[] for cam in cameras: focals.append(cam.focal) sorted(focals) if len(focals)%2==1: warped_image_scale = focals[len(focals) // 2] else: warped_image_scale = (focals[len(focals) // 2]+focals[len(focals) // 2-1])/2 if do_wave_correct: rmats=[] for cam in cameras: rmats.append(np.copy(cam.R)) rmats = cv.detail.waveCorrect( rmats, cv.detail.WAVE_CORRECT_HORIZ) for idx,cam in enumerate(cameras): cam.R = rmats[idx] corners=[] mask=[] masks_warped=[] images_warped=[] sizes=[] masks=[] for i in range(0,num_images): um=cv.UMat(255*np.ones((images[i].shape[0],images[i].shape[1]),np.uint8)) masks.append(um) warper = cv.PyRotationWarper(warp_type,warped_image_scale*seam_work_aspect) # warper peut etre nullptr? for idx in range(0,num_images): K = cameras[idx].K().astype(np.float32) swa = seam_work_aspect K[0,0] *= swa K[0,2] *= swa K[1,1] *= swa K[1,2] *= swa corner,image_wp =warper.warp(images[idx],K,cameras[idx].R,cv.INTER_LINEAR, cv.BORDER_REFLECT) corners.append(corner) sizes.append((image_wp.shape[1],image_wp.shape[0])) images_warped.append(image_wp) p,mask_wp =warper.warp(masks[idx],K,cameras[idx].R,cv.INTER_NEAREST, cv.BORDER_CONSTANT) masks_warped.append(mask_wp.get()) images_warped_f=[] for img in images_warped: imgf=img.astype(np.float32) images_warped_f.append(imgf) if cv.detail.ExposureCompensator_CHANNELS == expos_comp_type: compensator = cv.detail_ChannelsCompensator(expos_comp_nr_feeds) # compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering) elif cv.detail.ExposureCompensator_CHANNELS_BLOCKS == expos_comp_type: compensator=cv.detail_BlocksChannelsCompensator(expos_comp_block_size, expos_comp_block_size,expos_comp_nr_feeds) # compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering) else: compensator=cv.detail.ExposureCompensator_createDefault(expos_comp_type) compensator.feed(corners=corners, images=images_warped, masks=masks_warped) if seam_find_type == "no": seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_NO) elif seam_find_type == "voronoi": seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM); elif seam_find_type == "gc_color": seam_finder = cv.detail_GraphCutSeamFinder("COST_COLOR") elif seam_find_type == "gc_colorgrad": seam_finder = cv.detail_GraphCutSeamFinder("COST_COLOR_GRAD") elif seam_find_type == "dp_color": seam_finder = cv.detail_DpSeamFinder("COLOR") elif seam_find_type == "dp_colorgrad": seam_finder = cv.detail_DpSeamFinder("COLOR_GRAD") if seam_finder is None: print("Can't create the following seam finder ",seam_find_type) exit() seam_finder.find(images_warped_f, corners,masks_warped ) imgListe=[] compose_scale=1 corners=[] sizes=[] images_warped=[] images_warped_f=[] masks=[] blender= None timelapser=None compose_work_aspect=1 for idx,name in enumerate(img_names): # https://github.com/opencv/opencv/blob/master/samples/cpp/stitching_detailed.cpp#L725 ? full_img = cv.imread(name) if not is_compose_scale_set: if compose_megapix > 0: compose_scale = min(1.0, np.sqrt(compose_megapix * 1e6 / (full_img.shape[0]*full_img.shape[1]))) is_compose_scale_set = True; compose_work_aspect = compose_scale / work_scale; warped_image_scale *= compose_work_aspect warper = cv.PyRotationWarper(warp_type,warped_image_scale) for i in range(0,len(img_names)): cameras[i].focal *= compose_work_aspect cameras[i].ppx *= compose_work_aspect cameras[i].ppy *= compose_work_aspect sz = (full_img_sizes[i][0] * compose_scale,full_img_sizes[i][1]* compose_scale) K = cameras[i].K().astype(np.float32) roi = warper.warpRoi(sz, K, cameras[i].R); corners.append(roi[0:2]) sizes.append(roi[2:4]) if abs(compose_scale - 1) > 1e-1: img =cv.resize(src=full_img, dsize=None, fx=compose_scale, fy=compose_scale, interpolation=cv.INTER_LINEAR_EXACT) else: img = full_img; img_size = (img.shape[1],img.shape[0]); K=cameras[idx].K().astype(np.float32) corner,image_warped =warper.warp(img,K,cameras[idx].R,cv.INTER_LINEAR, cv.BORDER_REFLECT) mask =255*np.ones((img.shape[0],img.shape[1]),np.uint8) p,mask_warped =warper.warp(mask,K,cameras[idx].R,cv.INTER_NEAREST, cv.BORDER_CONSTANT) compensator.apply(idx,corners[idx],image_warped,mask_warped) image_warped_s = image_warped.astype(np.int16) image_warped=[] dilated_mask = cv.dilate(masks_warped[idx],None) seam_mask = cv.resize(dilated_mask,(mask_warped.shape[1],mask_warped.shape[0]),0,0,cv.INTER_LINEAR_EXACT) mask_warped = cv.bitwise_and(seam_mask,mask_warped) if blender==None and not timelapse: blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO) dst_sz = cv.detail.resultRoi(corners=corners,sizes=sizes) blend_width = np.sqrt(dst_sz[2]*dst_sz[3]) * blend_strength / 100 if blend_width < 1: blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO) elif blend_type == "multiband": blender = cv.detail_MultiBandBlender() blender.setNumBands((np.log(blend_width)/np.log(2.) - 1.).astype(np.int)) elif blend_type == "feather": blender = cv.detail_FeatherBlender() blender.setSharpness(1./blend_width) blender.prepare(dst_sz) elif timelapser==None and timelapse: timelapser = cv.detail.Timelapser_createDefault(timelapse_type) timelapser.initialize(corners, sizes) if timelapse: matones=np.ones((image_warped_s.shape[0],image_warped_s.shape[1]), np.uint8) timelapser.process(image_warped_s, matones, corners[idx]) pos_s = img_names[idx].rfind("/"); if pos_s == -1: fixedFileName = "fixed_" + img_names[idx]; else: fixedFileName = img_names[idx][:pos_s + 1 ]+"fixed_" + img_names[idx][pos_s + 1: ] cv.imwrite(fixedFileName, timelapser.getDst()) else: blender.feed(cv.UMat(image_warped_s), mask_warped, corners[idx]) if not timelapse: result=None result_mask=None result,result_mask = blender.blend(result,result_mask) cv.imwrite(result_name,result) zoomx = 600.0 / result.shape[1] dst=cv.normalize(src=result,dst=None,alpha=255.,norm_type=cv.NORM_MINMAX,dtype=cv.CV_8U) dst=cv.resize(dst,dsize=None,fx=zoomx,fy=zoomx) cv.imshow(result_name,dst) cv.waitKey() print('Done')
if estimator_type == "affine": estimator = cv.detail_AffineBasedEstimator() else: estimator = cv.detail_HomographyBasedEstimator() b, cameras =estimator.apply(features,p,None) if not b: print("Homography estimation failed.") exit() for cam in cameras: cam.R=cam.R.astype(np.float32) if ba_cost_func == "reproj": adjuster = cv.detail_BundleAdjusterReproj() elif ba_cost_func == "ray": adjuster = cv.detail_BundleAdjusterRay() elif ba_cost_func == "affine": adjuster = cv.detail_BundleAdjusterAffinePartial() elif ba_cost_func == "no": adjuster = cv.detail_NoBundleAdjuster() else: print( "Unknown bundle adjustment cost function: ", ba_cost_func ) exit() adjuster.setConfThresh(1) refine_mask=np.zeros((3,3),np.uint8) if ba_refine_mask[0] == 'x': refine_mask[0,0] = 1 if ba_refine_mask[1] == 'x': refine_mask[0,1] = 1 if ba_refine_mask[2] == 'x': refine_mask[0,2] = 1
if estimator_type == "affine": estimator = cv.detail_AffineBasedEstimator() else: estimator = cv.detail_HomographyBasedEstimator() b, cameras = estimator.apply(features, p, None) if not b: print("Homography estimation failed.") exit() for cam in cameras: cam.R = cam.R.astype(np.float32) if ba_cost_func == "reproj": adjuster = cv.detail_BundleAdjusterReproj() elif ba_cost_func == "ray": adjuster = cv.detail_BundleAdjusterRay() elif ba_cost_func == "affine": adjuster = cv.detail_BundleAdjusterAffinePartial() elif ba_cost_func == "no": adjuster = cv.detail_NoBundleAdjuster() else: print("Unknown bundle adjustment cost function: ", ba_cost_func) exit() adjuster.setConfThresh(1) refine_mask = np.zeros((3, 3), np.uint8) if ba_refine_mask[0] == 'x': refine_mask[0, 0] = 1 if ba_refine_mask[1] == 'x': refine_mask[0, 1] = 1 if ba_refine_mask[2] == 'x': refine_mask[0, 2] = 1
class Stitch2: finder = cv.ORB.create() matcher = cv.detail.BestOfNearestMarcher_create(False, 0.3) warp_type = "cylindrical" p = list() last_p = list() estimator = cv.detail_HomographyBasedEstimator() adjustor = cv.detail_BundleAdjusterRay() seam_finder = cv.detail_DpSeamFinder("COLOR_GRAD") all_cameras = list() focals = list() rmats = list() work_scale = 0.6 seam_scale = 0.25 conf_thresh = 0.3 seam_work_aspect = 1 full_img_sizes = [] features = [] images = [] is_work_scale_set = False is_seam_scale_set = False is_compose_scale_set = False do_wave_correct = True images = list() features = list() def __init__(self, img1): # first image push to list self._get_refine_mask() self._getWarper() self._getCompensator() self._getMask(img1) self.__appendImg(img1) def __appendImg(self, full_img): self.full_img_sizes.append((full_img.shape[1], full_img.shape[0])) self._getMask(full_img) if self.work_megapix < 0: img = full_img self.work_scale = 1 self.is_work_scale_set = True else: if self.is_work_scale_set is False: self.work_scale = min( 1.0, np.sqrt(self.work_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1]))) self.is_work_scale_set = True img = cv.resize(src=full_img, dsize=None, fx=self.work_scale, fy=self.work_scale, interpolation=cv.INTER_LINEAR_EXACT) if self.is_seam_scale_set is False: self.seam_scale = min( 1.0, np.sqrt(self.seam_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1]))) self.seam_work_aspect = self.seam_scale / self.work_scale self.is_seam_scale_set = True img_feat = cv.detail.computeImageFeatures2(self.finder, img) self.features.append(img_feat) img = cv.resize(src=full_img, dsize=None, fx=self.seam_scale, fy=self.seam_scale, interpolation=cv.INTER_LINEAR_EXACT) self.images.append(img) def getNew(self, img2): # get new images and calculate all self.__appendImg(img2) img_feat = cv.detail.computeImageFeatures2(self.finder, img2) self.features.append(img_feat) def matchImg(self): # get matcher for last two features _p = self.matcher.apply2(self.features[-2:]) self.last_p = _p self.p.append(_p) # append the maching info to previous info self.matcher.collectGarbage() def _get_refine_mask(self): # set mask # apply to last two features? self.refine_mask = np.zeros((3, 3), np.uint8) self.refine_mask[0, 0] = 1 self.refine_mask[0, 1] = 1 self.refine_mask[0, 2] = 1 self.refine_mask[1, 1] = 1 self.refine_mask[1, 2] = 1 def estimateImg(self): # cameras is the last two camera b, cameras = self.estimator.apply(self.features[-2:], self.last_p, None) if not b: print("Homography estimation failed.") exit() for cam in cameras: cam.R = cam.R.astype(np.float32) self.adjustor.setConfThresh(0.3) self.adjuster.setRefinementMask(self.refine_mask) b, cameras = self.adjuster.apply(self.features[-2:], self.last_p, cameras) if not b: print("Camera parameters adjusting failed.") return # append last two/one? camera to all_cameras self.all_cameras.append(cameras[-1]) # append last two/one? camera's focals for cam in cameras: self.focals.append(cam.focal) self.rmats.append(np.copy(cam.R)) self.focals.sort() if len(self.focals) % 2 == 1: # get median self.warped_image_scale = self.focals[len(self.focals) // 2] else: self.warped_image_scale = ( self.focals[len(self.focals) // 2] + self.focals[len(self.focals) // 2 - 1]) / 2 corners = [] masks_warped = [] images_warped = [] images_warped_f = [] sizes = [] masks = [] def waveCorrect(self): if self.do_wave_correct: self.rmats = cv.detail.waveCorrect(self.rmats, cv.detail.WAVE_CORRECT_HORIZ) for idx, cam in enumerate(self.all_cameras): cam.R = self.rmats[idx] def _getMask(self, img): um = cv.UMat(255 * np.ones((img.shape[0], img.shape[1]), np.uint8)) self.masks.append(um) def _getWarper(self): self.warper = cv.PyRotationWarper( self.warp_type, self.warped_image_scale * self.seam_work_aspect) # warper could be nullptr? def getNewMaskWarped(self): idx = -1 K = self.all_cameras[idx].K().astype(np.float32) swa = self.seam_work_aspect K[0, 0] *= swa K[0, 2] *= swa K[1, 1] *= swa K[1, 2] *= swa corner, image_wp = self.warper.warp(self.images[idx], K, self.all_cameras[idx].R, cv.INTER_LINEAR, cv.BORDER_REFLECT) self.corners.append(corner) self.sizes.append((image_wp.shape[1], image_wp.shape[0])) self.images_warped.append(image_wp) p, mask_wp = self.warper.warp(self.masks[idx], K, self.all_cameras[idx].R, cv.INTER_NEAREST, cv.BORDER_CONSTANT) self.masks_warped.append(mask_wp.get()) imgf = image_wp.astype(np.float32) self.images_warped_f.append(imgf) def _getCompensator(self): expos_comp_block_size = 32 expos_comp_nr_feeds = 1 self.compensator = cv.detail_BlocksChannelsCompensator( expos_comp_block_size, expos_comp_block_size, expos_comp_nr_feeds) def applyCompensator(self): self.compensator.feed(corners=self.corners, images=self.images_warped, masks=self.masks_warped) def applySeamFinder(self): self.seam_finder.find(self.images_warped_f, self.corners, self.masks_warped) def applyBlender(self): for idx, full_img in enumerate(self.images): if not self.is_compose_scale_set: if self.compose_megapix > 0: compose_scale = min( 1.0, np.sqrt(self.compose_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1]))) self.is_compose_scale_set = True compose_work_aspect = self.compose_scale / self.work_scale self.warped_image_scale *= compose_work_aspect # a new warper warper = cv.PyRotationWarper(self.warp_type, self.warped_image_scale) for i in range(0, len(img_names)): cameras[i].focal *= compose_work_aspect cameras[i].ppx *= compose_work_aspect cameras[i].ppy *= compose_work_aspect sz = (full_img_sizes[i][0] * compose_scale, full_img_sizes[i][1] * compose_scale) K = cameras[i].K().astype(np.float32) roi = warper.warpRoi(sz, K, cameras[i].R) corners.append(roi[0:2]) sizes.append(roi[2:4]) def getAllMasksWarped(self): warper = cv.PyRotationWarper( self.warp_type, self.warped_image_scale * self.seam_work_aspect) # warper could be nullptr? num_images = self.images.count for idx in range(0, num_images): K = self.all_cameras[idx].K().astype(np.float32) swa = self.seam_work_aspect K[0, 0] *= swa K[0, 2] *= swa K[1, 1] *= swa K[1, 2] *= swa corner, image_wp = warper.warp(self.images[idx], K, self.all_cameras[idx].R, cv.INTER_LINEAR, cv.BORDER_REFLECT) self.corners.append(corner) self.sizes.append((image_wp.shape[1], image_wp.shape[0])) self.images_warped.append(image_wp) p, mask_wp = warper.warp(self.masks[idx], K, self.all_cameras[idx].R, cv.INTER_NEAREST, cv.BORDER_CONSTANT) self.masks_warped.append(mask_wp.get()) for img in self.images_warped: imgf = img.astype(np.float32) self.images_warped_f.append(imgf)