OpenCV4兼容OpenCV2重映射函数及插值标志问题技术问询
光场显微镜校准代码移植解决方案(Python3+OpenCV4.x)
问题核心
原代码中cv.Remap的三个标志在OpenCV4.x中已变更:
cv.CV_INTER_LINEAR→cv.INTER_LINEARcv.CV_WARP_INVERSE_MAP:OpenCV3+的cv.remap默认采用目标像素→源像素的映射逻辑,与该标志的原行为一致,无需额外指定cv.CV_WARP_FILL_OUTLIERS:该功能移至borderMode参数,通过cv.BORDER_CONSTANT实现边界填充
修改后的完整代码
# 图像扭曲函数 # 输入input_image需为numpy float32数组,返回处理后的图像 def warp_image(self, input_image, output_pixels_per_lenslet, direction="R", cropToInside=False, lenslet_offset=None, output_size=None): im = input_image ul = self.eval_point([0, 0], 'f') ur = self.eval_point([0, im.shape[1]], 'f') ll = self.eval_point([im.shape[0], 0], 'f') lr = self.eval_point([im.shape[0], im.shape[1]], 'f') leftbound = np.ceil(max(ul[1], ll[1])) rightbound = np.floor(min(ur[1], lr[1])) topbound = np.ceil(max(ul[0], ur[0])) bottombound = np.floor(min(ll[0], lr[0])) # 不裁剪透镜阵列左侧(0,y)或上方(x,0)区域 leftbound = max(leftbound, 0) topbound = max(topbound, 0) if output_size is not None: putative_output_size = output_size else: nt = int(np.floor(bottombound - topbound)) ns = int(np.floor(rightbound - leftbound)) putative_output_size = (nt * output_pixels_per_lenslet, ns * output_pixels_per_lenslet) # 计算映射坐标 scaled_shift = (0.0, 0.0) if direction.upper() == 'F': coeff = np.copy(self.forwardCoefficients) coeff[:,1:] *= output_pixels_per_lenslet coeff[:,3:] *= output_pixels_per_lenslet coeff[:,6:] *= output_pixels_per_lenslet if lenslet_offset is not None: scaled_shift = (lenslet_offset[0] / output_pixels_per_lenslet, lenslet_offset[1] / output_pixels_per_lenslet) else: coeff = np.copy(self.reverseCoefficients) coeff[:,1:] /= output_pixels_per_lenslet coeff[:,3:] /= output_pixels_per_lenslet coeff[:,6:] /= output_pixels_per_lenslet if lenslet_offset is not None: scaled_shift = (lenslet_offset[0] * output_pixels_per_lenslet, lenslet_offset[1] * output_pixels_per_lenslet) x, y = np.meshgrid(np.arange(putative_output_size[1], dtype='float32'), np.arange(putative_output_size[0], dtype='float32')) ix_array = (np.ones_like(x, dtype='float32') * coeff[0,0] + x * coeff[0,1] + y * coeff[0,2] + x*x * coeff[0,3] + x*y * coeff[0,4] + y*y * coeff[0,5] + x*x*x * coeff[0,6] + x*x*y * coeff[0,7] + x*y*y * coeff[0,8] + y*y*y * coeff[0,9] + scaled_shift[0]) iy_array = (np.ones_like(y, dtype='float32') * coeff[1,0] + x * coeff[1,1] + y * coeff[1,2] + x*x * coeff[1,3] + x*y * coeff[1,4] + y*y * coeff[1,5] + x*x*x * coeff[1,6] + x*x*y * coeff[1,7] + x*y*y * coeff[1,8] + y*y*y * coeff[1,9] + scaled_shift[1]) ix = ix_array.astype(np.float32) iy = iy_array.astype(np.float32) # OpenCV4.x版本的remap调用 # 采用线性插值,边界填充为0(与原CV_WARP_FILL_OUTLIERS行为一致) output_image = cv.remap(im, ix, iy, flags=cv.INTER_LINEAR, borderMode=cv.BORDER_CONSTANT, borderValue=0.0) # 裁剪逻辑 if cropToInside: return output_image[int(topbound * output_pixels_per_lenslet):int(bottombound * output_pixels_per_lenslet), int(leftbound * output_pixels_per_lenslet):int(rightbound * output_pixels_per_lenslet)] else: return output_image
关键改动说明
标志参数适配
- 移除
CV_WARP_INVERSE_MAP:OpenCV3+的cv.remap默认将ix/iy视为目标像素到源像素的映射坐标,与原代码该标志的行为完全一致 - 用
borderMode=cv.BORDER_CONSTANT替代CV_WARP_FILL_OUTLIERS:对超出源图像边界的映射像素填充固定值(这里设为0,与原逻辑一致)
- 移除
函数调用方式变更
- OpenCV4.x的
cv.remap无需预先创建输出图像,直接返回处理结果,简化了代码逻辑
- OpenCV4.x的
细节优化
- 用
np.ones_like(x)替代手动创建全1数组,更高效且易维护 - 修复了原代码中
if np.any(lenslet_offset) != None的错误判断,改为if lenslet_offset is not None,避免空值判断异常
- 用
内容的提问来源于stack exchange,提问作者Oğulcan Cingiler
相关产品推荐
相关产品推荐

