import cv2
import numpy as np
from copy import deepcopy
from .utils import histMatch, Image, ReadImageFile, GetOutputDriverFor
from osgeo import gdal, gdalconst
from osgeo import osr
[文档]def HISByFilePath(srcpath:str, panpath:str, resultpath:str, driver:str):
"""Using HIS 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
"""
HIS(ReadImageFile(srcpath), ReadImageFile(panpath), None, resultpath, driver)
[文档]def HIS(src:Image, pan:Image, block_size=None ,result_path=None, driver=None):
"""Using HIS method to fusion the image
The `source` image should not be upsampled
:param src: `source` image, it should be `pyfusion.utils.Image` type
: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
dstImage[y_start:y_end, x_start:x_end] = _HIS(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])
return dstImage
def _HIS(src, pan):
"""Using HIS method to fusion the image
The `source` image should not be upsampled
:param src: `source` image, the image should be BGR color space
:param pan: Panchromatic image, the image should be grayscale
:return: fusion image
:rtype: `numpy.ndarray`
"""
# upsamply the image
img_rgb = cv2.resize(src, tuple(reversed(pan.shape)))
if np.max(img_rgb) == 0:
return np.zeros(img_rgb.shape, dtype=np.uint8)
# convert the color space
img_HLS = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HLS)
# histogram match
dst_pan = histMatch(pan, img_HLS[:,:,1])
# merge the new image
img_fusion_HLS = cv2.merge((img_HLS[:,:,0], dst_pan, img_HLS[:,:,2]))
del img_HLS
del dst_pan
# convert color space
img_fusion_BGR = cv2.cvtColor(img_fusion_HLS, cv2.COLOR_HLS2RGB)
return img_fusion_BGR