import cv2
import numpy as np
from .utils import Image, ReadImageFile, GetOutputDriverFor
from osgeo import gdal, gdalconst
[文档]def BroveryByFilePath(srcpath:str, panpath:str, resultpath:str, driver:str):
"""Using Brovery method fusion image
The output only support tif format
:param srcpath: `source` image path
:param panpath: Panchromatic image path
:param resultpath: result image path
:return: None
:rtype: None
"""
Brovery(ReadImageFile(srcpath), ReadImageFile(panpath), None, resultpath, driver)
[文档]def Brovery(src:Image, pan:Image, block_size=None ,result_path=None, driver=None):
"""
Using Brovery method to fusion image
The source image should not be upsampled
:param src: `source` image, the image should be RGB color space
:param pan: Panchromatic image, the image should be grayscale
:param block_size: block_size
:param result_path: result image path, it can be any format supported by gdal
:param driver: gdal write driver
:return: fusion image
:rtype: `pyfusion.utils.Image`
"""
assert src.image.RasterCount == 3, "src image should be 3 bands"
assert pan.image.RasterCount == 1, "pan image should be 1 band"
if block_size is None:
block_size = 4096
dstDs = None
# if not result_path, it will store the result into memory
if result_path is None:
driver = gdal.GetDriverByName("MEM")
dstDs = driver.Create("", pan.image.RasterXSize, pan.image.RasterYSize, 3, options=["INTERLEAVE=PIXEL"])
# if give result_path, it will write result into file
elif driver is not None:
driver = gdal.GetDriverByName(driver)
dstDs = driver.Create(result_path, pan.image.RasterXSize, pan.image.RasterYSize, 3, options=["INTERLEAVE=PIXEL"])
else:
driver = GetOutputDriverFor(result_path)
dstDs = driver.Create(result_path, pan.image.RasterXSize, pan.image.RasterYSize, 3, options=["INTERLEAVE=PIXEL"])
dstDs.SetGeoTransform(pan.image.GetGeoTransform())
dstDs.SetProjection(pan.image.GetProjection())
dstDs.SetSpatialRef(pan.image.GetSpatialRef())
dstImage = Image(dstDs)
xsize = dstImage.image.RasterXSize
ysize = dstImage.image.RasterYSize
x_blocks = xsize // block_size
y_blocks = ysize // block_size
if x_blocks == 0:
x_blocks += 1
if y_blocks == 0:
y_blocks += 1
x_size_true = (xsize // x_blocks) + 1
y_size_true = (ysize // y_blocks) + 1
x_rate, y_rate = src.image.RasterXSize/xsize, src.image.RasterYSize/ysize
for i in range(x_blocks):
for j in range(y_blocks):
x_start, y_start = i*x_size_true, j*y_size_true
x_end, y_end = i*x_size_true+x_size_true, j*y_size_true+y_size_true
if x_end > xsize:
x_end = xsize
if y_end > ysize:
y_end = ysize
try:
dstImage[y_start:y_end, x_start:x_end] = _Brovery(src[int(y_start*y_rate):int(y_end*y_rate), int(x_start*x_rate):int(x_end*x_rate)], pan[y_start:y_end, x_start:x_end])
except Exception as e:
print(x_start, x_end, y_start, y_end)
print(int(x_start*x_rate), int(x_end*x_rate), int(y_start*y_rate), int(y_end*y_rate))
print(i, j)
print(x_blocks, y_blocks)
print(x_size_true, y_size_true)
print(xsize, ysize)
raise e
return dstImage
def _Brovery(src, pan):
"""
Using Brovery method to fusion image
The source image should not be upsampled
:param src: `source` image, the image should be RGB color space
:param pan: Panchromatic image, the image should be grayscale
:return: fusion image
:rtype: `numpy.ndarray`
"""
img_bgr = cv2.resize(src, tuple(reversed(pan.shape)))
if np.max(img_bgr) == 0:
return np.zeros(img_bgr.shape ,dtype=np.uint8)
pan = pan.astype(np.float32)
r,g,b = cv2.split(img_bgr)
b = b.astype(np.float32)
g = g.astype(np.float32)
r = r.astype(np.float32)
rf = (3*pan)*r/(b+g+r)
gf = (3*pan)*g/(b+g+r)
bf = (3*pan)*b/(b+g+r)
bf = bf.astype(np.uint8)
gf = gf.astype(np.uint8)
rf = rf.astype(np.uint8)
img_brovery = cv2.merge((rf,gf,bf))
return img_brovery