56 lines
2 KiB
Python
56 lines
2 KiB
Python
import cv2 as cv
|
|
import numpy as np
|
|
|
|
|
|
class Blender:
|
|
|
|
BLENDER_CHOICES = ('multiband', 'feather', 'no',)
|
|
DEFAULT_BLENDER = 'multiband'
|
|
DEFAULT_BLEND_STRENGTH = 5
|
|
|
|
def __init__(self, blender_type=DEFAULT_BLENDER,
|
|
blend_strength=DEFAULT_BLEND_STRENGTH):
|
|
self.blender_type = blender_type
|
|
self.blend_strength = blend_strength
|
|
self.blender = None
|
|
|
|
def prepare(self, corners, sizes):
|
|
dst_sz = cv.detail.resultRoi(corners=corners, sizes=sizes)
|
|
blend_width = (np.sqrt(dst_sz[2] * dst_sz[3]) *
|
|
self.blend_strength / 100)
|
|
|
|
if self.blender_type == 'no' or blend_width < 1:
|
|
self.blender = cv.detail.Blender_createDefault(
|
|
cv.detail.Blender_NO
|
|
)
|
|
|
|
elif self.blender_type == "multiband":
|
|
self.blender = cv.detail_MultiBandBlender()
|
|
self.blender.setNumBands(int((np.log(blend_width) /
|
|
np.log(2.) - 1.)))
|
|
|
|
elif self.blender_type == "feather":
|
|
self.blender = cv.detail_FeatherBlender()
|
|
self.blender.setSharpness(1. / blend_width)
|
|
|
|
self.blender.prepare(dst_sz)
|
|
|
|
def feed(self, img, mask, corner):
|
|
"""https://docs.opencv.org/4.x/d6/d4a/classcv_1_1detail_1_1Blender.html#a64837308bcf4e414a6219beff6cbe37a""" # noqa
|
|
self.blender.feed(cv.UMat(img.astype(np.int16)), mask, corner)
|
|
|
|
def blend(self):
|
|
"""https://docs.opencv.org/4.x/d6/d4a/classcv_1_1detail_1_1Blender.html#aa0a91ce0d6046d3a63e0123cbb1b5c00""" # noqa
|
|
result = None
|
|
result_mask = None
|
|
result, result_mask = self.blender.blend(result, result_mask)
|
|
result = cv.convertScaleAbs(result)
|
|
return result, result_mask
|
|
|
|
@classmethod
|
|
def create_panorama(cls, imgs, masks, corners, sizes):
|
|
blender = cls("no")
|
|
blender.prepare(corners, sizes)
|
|
for img, mask, corner in zip(imgs, masks, corners):
|
|
blender.feed(img, mask, corner)
|
|
return blender.blend()
|