tiff转图片

发布时间 2023-12-11 11:34:09作者: Alphapy

tiff转图片jpg/png

存在的问题

  1. 原博客程序内存占用过大,部署在docker后容器异常重启,故修改dtype为float16减小内存占用。

  2. chrome浏览器图片显示存在对像素点数量的限制,超出指定大小则图片加载失败,故需要对图片进行缩小,降低像素点数量。

  3. 参考博客无灰度图转化方法,本文在搜集多方资料后进行补充。

  4. jpg图像为3通道,背景颜色显示为黑色。若要去黑框,将图片黑色背景改为透明,则需要保存图片为png格式,将3通道转为4通道(添加透明通道)。

  5. 生成的png图片文件太大,前端展示速度较慢,故需压缩图片,使网页端能够快速预览。

opencv2实现

tiff转jpg

import cv2
import numpy as np

from skimage import io
from loguru import logger


def tiff2jpg(tiff_file_path, jpg_file_path, scale=0.3):
    """
    将tiff文件转为jpg图片
    :param tiff_file_path: tiff文件路径
    :param jpg_file_path: 生成的图片路径
    :param scale: 图像缩放比例
    """
    logger.info("开始生成缩略图")
    try:
        img = io.imread(tiff_file_path)  # 读取文件名
        logger.info(f"图片尺寸: {img.shape}; 数据类型: {img.dtype}")  # 显示图片大小和类型
        img = np.divide(img, img.max(), dtype=np.float16)  # 使其所有值不大于一
        img = img * 255 - 0.001  # 减去0.001防止变成负整型
        img = img.astype(np.uint8)  # 强制转换成8位整型
        if len(img.shape) == 3:
            height, width, _ = img.shape
            img_resize = cv2.resize(img, dsize=(round(width * scale), round(height * scale)))
            b = img_resize[:, :, 0]    # 读取蓝通道
            g = img_resize[:, :, 1]    # 读取绿通道
            r = img_resize[:, :, 2]    # 读取红通道
            rgb_img = cv2.merge([r, g, b])  # 通道拼接
            cv2.imwrite(jpg_file, rgb_img)  # 保存图像
        elif len(img.shape) == 2:
            height, width = img.shape
            img_resize = cv2.resize(img, dsize=(round(width * scale), round(height * scale)))
            rgb_image = cv2.cvtColor(img_resize, cv2.COLOR_GRAY2RGB)
            b = rgb_image[:, :, 0]  # 读取蓝通道
            g = rgb_image[:, :, 1]  # 读取绿通道
            r = rgb_image[:, :, 2]  # 读取红通道
            rgb_img = cv2.merge([r, g, b])  # 通道拼接
            cv2.imwrite(jpg_file_path, rgb_img)  # 保存图像

        logger.info(f"生成缩略图成功: {jpg_file_path}")
    except Exception as e:
        logger.error(f"生成缩略图失败: {e}")

tiff转png

import cv2
import numpy as np

from skimage import io
from loguru import logger


def tiff2png(tiff_file_path, png_file_path, scale=0.3):
    """
    将tiff文件转为png图片
    :param tiff_file_path: tiff文件路径
    :param png_file_path: 生成的图片路径
    :param scale: 图像缩放比例
    """
    logger.info("开始生成缩略图")
    try:
        img = io.imread(tiff_file_path)  # 读取文件名
        logger.info(f"图片尺寸: {img.shape}; 数据类型: {img.dtype}")  # 显示图片尺寸和类型
        img = np.divide(img, img.max(), dtype=np.float16)  # 使其所有值不大于1
        img = img * 255 - 0.001  # 减去0.001防止变成负整型
        img = img.astype(np.uint8)  # 强制转换成8位整型
        if len(img.shape) == 3:
            height, width, _ = img.shape
            # 注意顺序: width, height
            img_resize = cv2.resize(img, dsize=(round(width * scale), round(height * scale)))
            b = img_resize[:, :, 0]    # 读取蓝通道
            g = img_resize[:, :, 1]    # 读取绿通道
            r = img_resize[:, :, 2]    # 读取红通道
            rgb_img = cv2.merge([b, g, r])  # 通道拼接
            # 三通道转四通道,设置黑色为透明
            gray_image = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2GRAY)
            _, alpha = cv2.threshold(gray_image, 0, 255, cv2.THRESH_BINARY)
            rgba_image = cv2.merge([b, g, r, alpha], 4)
            # 如需轮廓识别,可添加代码在此处
            # 保存图像,极限压缩
            cv2.imwrite(png_file_path, rgba_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])
        elif len(img.shape) == 2:
            height, width = img.shape
            # 注意顺序: width, height
            img_resize = cv2.resize(img, dsize=(round(width * scale), round(height * scale)))
            rgb_image = cv2.cvtColor(img_resize, cv2.COLOR_GRAY2RGB)
            b = rgb_image[:, :, 0]  # 读取蓝通道
            g = rgb_image[:, :, 1]  # 读取绿通道
            r = rgb_image[:, :, 2]  # 读取红通道
            _, alpha = cv2.threshold(img_resize, 0, 255, cv2.THRESH_BINARY)
            rgba_image = cv2.merge([b, g, r, alpha], 4)
            # 保存图像,极限压缩
            cv2.imwrite(png_file_path, rgba_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])

        logger.info(f"生成缩略图成功: {png_file_path}")
    except Exception as e:
        logger.error(f"生成缩略图失败: {e}")

轮廓识别

# 识别轮廓,裁剪图像
contours, _ = cv2.findContours(alpha, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
x, y, w, h = cv2.boundingRect(contours[0])
# 绘制轮廓
cv2.drawContours(dst, contours, 0, (0, 0, 255), 5)
# 提取图像范围
cropped_image = dst[y:y + h, x:x + w]

pillow实现

需要注意的是,此方法并不通用,经测试只有GF3系列可用。

tiff转jpg

# 读取tiff文件
tif_image = Image.open(tiff_file_path)
# 转换为RGB格式
rgb_image = tif_image.convert("RGB")
# 保存图像
rgb_image.save(jpg_file_path)

tiff转png

# 读取tiff文件
tif_image = Image.open(tiff_file_path)
# 转换为RGB格式
rgb_image = tif_image.convert("RGB")
# 创建alpha通道
_, alpha = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY)
# 通道分离
r, g, b = rgb_image.split()
# 将ndnaary类型转化为IMAGE类型
a = Image.fromarray(alpha)
# 通道融合
rgba_image = Image.merge("RGBA", [r, g, b, a])
# 图像尺寸
height, width = img.shape
# 图像等比例缩小
image_resize = rgba_image.resize((round(width * scale), round(height * scale)), Resampling.NEAREST)
# 获取图像的边界框
bbox = image_resize.getbbox()
# 裁剪图像,删除黑色边框
cropped_image = image_resize.crop(bbox)
# 保存为jpg图像
image_resize.save(png_file_path)

参考博客

  1. python将.tif格式图批量转化为.jpg格式图_python tif转jpg-CSDN博客

  2. OpenCV-Python教程:通道分离、通道合并(split、merge) – 桔子code (juzicode.com)

  3. Python 旋转图像并裁剪黑边|极客教程 (geek-docs.com)

  4. 【OpenCV】将图片黑色背景变成透明背景_opencv把黑色背景换成透明-CSDN博客

  5. python CV2中shape和resize返回值和参数的区别_cv2.shape-CSDN博客

  6. cv2.findContours() 轮廓检测_cv2.findcontours所有点-CSDN博客

  7. python cv2 改变图片黑色背景改为透明_mob64ca12e95b2b的技术博客_51CTO博客

  8. 3.4. 使用 Pillow 处理图像:通道 — Python笔记 文档 (osgeo.cn)

  9. Python图片处理模块PIL操作方法(pillow)-腾讯云开发者社区-腾讯云 (tencent.com)