图像批量增强之翻转、缩放、旋转、剪裁(附python源码)

一、引言

图像处理是一种广泛应用于各个领域的技术,其中包括图像识别、图像增强、图像恢复、图像分析等。在图像处理中,常常需要进行一些基本的操作,如图像翻转、图像缩放、图像旋转和图像剪裁等。这些操作都是非常基本的图像操作,它们可以用来改变图像的方向、大小和形状,从而满足不同的需求。

本文将对图像的下列操作进行介绍和提供源码:可设定水平、竖直或同时翻转,可设定长和宽放大比例的缩放,按一定的中心点进行旋转,可定义次数和剪裁比例的随机剪裁。

二、图像翻转

(1)翻转的形式

1. 水平翻转

在图像处理中,水平翻转是一种常见的操作。它是指将图像进行左右翻转。

2. 垂直翻转

垂直翻转是将图像上下翻转。

3. 镜像翻转

镜像翻转是指将图像沿着垂直或者水平轴进行翻转,产生镜像效果。

(2)代码展示:

import os  
import cv2  
import numpy as np  
from matplotlib import pyplot as plt  
  
def bgr2rbg(img):  
    '''  
        将颜色空间从BGR转换为RBG  
    '''  
    return img[:,:,::-1]  
  
def flip_image(img, flip_code):  
    '''  
        根据flip_code进行翻转  
    '''  
    return cv2.flip(img, flip_code)  
  
def process_folder(input_folder, output_folder, flip_code):  
    '''  
        对指定文件夹中的所有图片进行翻转并保存到新文件夹中  
    '''  
    if not os.path.exists(output_folder):  
        os.makedirs(output_folder)  
  
    file_count = 0  
    for filename in os.listdir(input_folder):  
        if filename.endswith('.jpg') or filename.endswith('.png'):  
            file_count += 1  
            img = cv2.imread(os.path.join(input_folder, filename))  
            flip_img = flip_image(img, flip_code)  
  
            # 生成唯一的输出文件名  
            output_filename = os.path.join(output_folder, f'{file_count:03d}_{flip_code}.jpg')  
            cv2.imwrite(output_filename, flip_img)   
            print(f'Processed {file_count} images and saved to {output_filename}')

(3)代码解释:

这段代码的功能是读取输入文件夹中的所有.jpg或.png图片,根据翻转代码(flip_code)进行翻转,并将翻转后的图片保存到输出文件夹中。

(4)使用示例:

你可以根据你自己的需要选择你所要进行翻转的方式,当然,翻转后你的图片并不会有任何的缺失。

你可以通过更改flip_code的值来选择翻转方式,可选值:'1'、'0'、'-1' 分别为水平翻转,竖直翻转和同时水平和垂直翻转 

input_folder = r"D:/soft/Notebook_workspace/myself/photo_add/01"  
output_folder_base = r"D:/soft/Notebook_workspace/myself/photo_add/12/"  
flip_code = 0  # 可选值:'1'、'0'、'-1' 分别为水平翻转,竖直翻转和同时水平和垂直翻转 
process_folder(input_folder, output_folder_base, flip_code)

(5)结果对比展示:

代码:需要转换的原因是因为opencv的颜色读取与正常图片不一样

def bgr2rbg(img):  
    '''  
        将颜色空间从BGR转换为RBG  
    '''  
    return img[:,:,::-1]  
  
img = cv2.imread(r"D:/soft/Notebook_workspace/myself/photo_add/01/001.jpg")
img = bgr2rbg(img)
dst = cv2.imread(r"D:/soft/Notebook_workspace/myself/photo_add/12/001_0.jpg")
dst = bgr2rbg(dst)
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()

 图片展示:

三、图像缩放

(1)缩放的形式

1.横向缩放,纵向不变

只对图像的宽度进行改变

2.纵向缩放,横向不变

只对图像的高度进行改变

3.横向和纵向同时缩放

图像的宽度和高度同时改变

缩放技术在实际应用中被广泛使用,例如:调整图像大小、图像压缩、分辨率转换等。

(2)代码展示:

from PIL import Image  
import os  
import numpy as np  
  
def resize_images(input_folder, output_folder, fx, fy):  
    # 检查输出文件夹是否存在,如果不存在则创建  
    if not os.path.exists(output_folder):  
        os.makedirs(output_folder)  
  
    # 获取输入文件夹中的所有图片文件  
    image_files = [f for f in os.listdir(input_folder) if f.endswith('.jpg') or f.endswith('.png')]  
  
    # 对每个图片文件进行处理  
    for i, image_file in enumerate(image_files):  
        try:  
            # 打开图片文件  
            with Image.open(os.path.join(input_folder, image_file)) as img:  
                # 获取图片的高度、宽度和通道数  
                original_height, original_width = img.size  
                channel = img.mode  
  
                # 创建变换矩阵 
                M = np.float32([[fx, 0, 0], [0, fy, 0]])  
                # 进行2D仿射变换  
                resized = img.resize((int(original_width*fx), int(original_height*fy)), Image.ANTIALIAS)  
  
                # 创建输出文件路径,添加图片编号和后缀  
                output_path = os.path.join(output_folder, f'{image_file[:-4]}_resized.jpg')  
  
                # 保存处理后的图片  
                resized.save(output_path)  
        except IOError as e:  
            print(f"无法读取文件 {image_file}: {e}")  
        except Exception as e:  
            print(f"处理图片 {image_file} 时发生异常: {e}")  
  

(3)代码解释:

这段代码的功能是读取指定文件夹中的所有.jpg或.png图片文件,然后按照给定的放大倍数(fx, fy)进行缩放,最后将处理后的图片保存到指定的输出文件夹中。 对图片按轴进行放大缩小,规定以像素点多的为x轴,少的为y轴 。

注意:本代码适合宽比高大的图片,否则会造成原图像较小的边变成宽,较长的一边变成高

(4)使用示例:

if __name__ == '__main__':  
    # 设置输入和输出文件夹路径  
    input_folder = r"D:/soft/Notebook_workspace/myself/photo_add/01/"
    output_folder = r"D:/soft/Notebook_workspace/myself/photo_add/11/"

    # 设置x和y轴的放大倍数  
    fx = 1.0  
    fy = 2.0  

    # 调用函数对文件夹中的图片进行放大和缩小处理  
    resize_images(input_folder, output_folder, fx, fy)

fx是x轴放大倍数,fy是y轴放大倍数

(5)结果展示: 

四、图像旋转

(1)旋转的形式

1.顺时针旋转

2.逆时针旋转

旋转技术常被用于照片处理、地图制作、游戏制作等领域。

 (2)代码1展示:

import os  
import cv2  
import numpy as np  
from math import cos, sin, radians  
from matplotlib import pyplot as plt  
  
def rotate_images(source_folder, target_folder, angles):  
    # 遍历指定文件夹中的所有图片文件  
    for filename in os.listdir(source_folder):  
        if filename.endswith('.jpg') or filename.endswith('.png'):  
            img_path = os.path.join(source_folder, filename)  
            img = cv2.imread(img_path)  
  
            height, width, channel = img.shape  
  
            # 计算图片中心点  
            cx = int(width / 2)  
            cy = int(height / 2)  
            center = (cx, cy)  
  
            new_dim = (width, height)  
  
            # 对每个角度进行旋转操作  
            rotated_images = []  
            for angle in angles:  
                # 获取旋转矩阵  
                M = cv2.getRotationMatrix2D(center=center, angle=angle, scale=1.0)  
                # 进行仿射变换  
                rotated = cv2.warpAffine(img, M, new_dim)  
                # 添加到旋转后的图片列表中  
                rotated_images.append(rotated)  
  
            # 将旋转后的图片保存到目标文件夹中  
            for i, rotated in enumerate(rotated_images):  
                # 获取原文件名,不包含后缀名  
                base_filename = os.path.splitext(filename)[0]  
                # 生成新的文件名,包含旋转角度后缀名  
                output_filename = f"{base_filename}_{angles[i]:03d}.jpg"  
                output_path = os.path.join(target_folder, output_filename)  
                cv2.imwrite(output_path, rotated)  
                print(f"Processed {output_path}")

(3)代码1解释:

 这段代码的功能是读取指定文件夹中的图片文件,对每个图片应用旋转操作,并将旋转后的图片保存到目标文件夹中。旋转中心为图片的中心,旋转前和旋转后图片的尺寸不会改变,这也就不可避免的使得图片会有一部分数据缺失,为了不缺失笔者对上述代码进行了改进,改进后的代码咱们向下看代码2。

(4)代码1使用示例:

通过改变angle内的值决定一次性进行多少种翻转。

if __name__ == '__main__':  
    source_folder = r"D:/soft/Notebook_workspace/myself/photo_add/01/" # 原文件夹路径  
    target_folder = r"D:/soft/Notebook_workspace/myself/photo_add/10/"  # 目标文件夹路径  
    angles = [30, 45, -60]  # 旋转角度列表,逆时针为正,顺时针为负  
    rotate_images(source_folder, target_folder, angles)

(5)代码2展示:

import os  
import cv2  
import numpy as np  
from math import cos, sin, radians  
from matplotlib import pyplot as plt  
  
def pad(img, top, bottom, left, right, value):  
    pad_img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=value)  
    return pad_img  
  
def rotate_images(source_folder, target_folder, angles, color):  
    # 检查目标文件夹是否存在,如果不存在则创建  
    if not os.path.exists(target_folder):  
        os.makedirs(target_folder)  
  
    # 遍历指定文件夹中的所有图片文件  
    for filename in os.listdir(source_folder):  
        if filename.endswith('.jpg') or filename.endswith('.png'):  
            try:  
                img_path = os.path.join(source_folder, filename)  
                img = cv2.imread(img_path)  
                height, width, channel = img.shape  
  
                # 计算图片中心点  
                cx = int(width / 2)  
                cy = int(height / 2)  
                center = (cx+cy, cy+cx)  
                pad_img = pad(img, cx, cx, cy, cy, color)  
                height, width, channel = pad_img.shape  
                new_dim = (width, height)  
  
                # 对每个角度进行旋转操作  
                rotated_images = []  
                for angle in angles:  
                    # 获取旋转矩阵  
                    M = cv2.getRotationMatrix2D(center=center, angle=angle, scale=1.0)  
                    # 进行仿射变换  
                    rotated = cv2.warpAffine(pad_img, M, new_dim)  
                    # 添加到旋转后的图片列表中  
                    rotated_images.append(rotated)  
  
                # 将旋转后的图片保存到目标文件夹中  
                for i, rotated in enumerate(rotated_images):  
                    # 获取原文件名,不包含后缀名  
                    base_filename = os.path.splitext(filename)[0]  
                    # 生成新的文件名,包含旋转角度后缀名  
                    output_filename = f"{base_filename}_{angles[i]:03d}.jpg"  
                    output_path = os.path.join(target_folder, output_filename)  
                    cv2.imwrite(output_path, rotated)  
                    print(f"Processed {output_path}")  
            except Exception as e:  
                print(f"Error processing {img_path}: {str(e)}")

(6)代码2解释:

相较于代码1增加的部分:先填充图片,自定义三通道填充颜色,图片填充为宽的左右各填充高的一半,高的上下各填充宽的一半,这样做的好处是通过增加图片大小来保证图片的完整性,当然,如果你想尽可能的减小图片的变化,你可以通过勾股定理计算原始图片距选择点最远的距离然后通过设置参数进行填充,这里笔者就不进行过多的描述了。

(6) 代码2使用示例:

其中color为填充颜色。

if __name__ == '__main__':  
    source_folder = r"D:/soft/Notebook_workspace/myself/photo_add/01/" # 原文件夹路径  
    target_folder = r"D:/soft/Notebook_workspace/myself/photo_add/14/"  # 目标文件夹路径  
    angles = [30, 45, -60]  # 旋转角度列表,逆时针为正,顺时针为负  
    color = (0, 0, 0)
    rotate_images(source_folder, target_folder, angles,color)
    

(7)结果对比显示:

1.代码1结果:

2.代码2结果:

五、图像剪裁

(1)剪裁的形式

1.裁剪区域指定

2.指定大小裁剪

3.同时指定裁剪

4..随机裁剪

前三种在上一篇博客中已经讲过,若有疑问,请移步至:图片剪裁

剪裁技术在照片处理、文档处理、网络传输等领域有着广泛的应用,通过剪裁技术可以有效地减小图像的尺寸和大小,从而加快网络传输速度和提高处理效率。同时,剪裁技术也可以有效地去掉背景噪声和无关信息,突出重要内容,提高图像质量。

(2)代码展示

from PIL import Image  
import os  
import random  
  
def random_crop(img, crop_ratio, crop_times):  
    """  
    对图片进行随机裁剪。  
      
    参数:  
        img: PIL Image对象  
        crop_ratio: 裁剪比率,例如 (0.3, 0.7) 表示在0.3到0.7的比例范围内随机选择  
        crop_times: 裁剪次数  
      
    返回:  
        裁剪后的图片列表  
    """  
    width, height = img.size  
    min_ratio, max_ratio = crop_ratio  
    cropped_imgs = []  
      
    for _ in range(crop_times):  
        crop_w = random.randint(int(width * min_ratio), int(width * max_ratio))  
        crop_h = random.randint(int(height * min_ratio), int(height * max_ratio))  
          
        left = random.randint(0, width - crop_w)  
        top = random.randint(0, height - crop_h)  
          
        cropped_img = img.crop((left, top, left + crop_w, top + crop_h))  
        cropped_imgs.append(cropped_img)  
      
    return cropped_imgs  
  
def process_folder(folder, save_path, crop_ratio=(0.3, 0.7), crop_times=5):  
    """  
    遍历文件夹中的所有文件,并对每个文件执行随机裁剪操作。  
      
    参数:  
        folder: 文件夹路径  
        crop_ratio: 裁剪比率,默认为(0.3, 0.7)  
        crop_times: 裁剪次数,默认为5  
    """  
    for subdir, dirs, files in os.walk(folder):  
        for file in files: 
            a, b = os.path.splitext(file)
            if file.endswith('.jpg') or file.endswith('.png'):  # 只处理JPEG和PNG格式的图片  
                img_path = os.path.join(subdir, file)  
                img = Image.open(img_path)  
                cropped_imgs = random_crop(img, crop_ratio, crop_times)  
                  
                for i, cropped_img in enumerate(cropped_imgs):  
                    cropped_img.save(save_path + a + "_" + str(i) + b)  # 保存裁剪后的图片为JPEG格式  

(3)代码解释

这段Python代码的功能是遍历指定文件夹中的所有图片文件,并对每个文件进行随机裁剪操作。裁剪操作由random_crop函数实现,该函数接受一个PIL Image对象、一个裁剪比例范围和一个裁剪次数作为输入,返回一个裁剪后的图片列表,最后保存到目标文件夹。

(4)使用示例

其中how是剪裁比例是原图片比例的大小范围,times1是每张图片的剪裁次数。本例中大小是0.3~0.7,裁剪三次。

if __name__ == '__main__':  
    folder = r"D:/soft/Notebook_workspace/myself/photo_add/01"  # 替换为你要操作的文件夹路径  
    save_path = r"D:/soft/Notebook_workspace/myself/photo_add/09/"
    how = (0.3, 0.7)
    times = 3
    process_folder(folder, save_path, how, times )

 (5)结果展示:

六、总结

本文主要介绍了几种图像增强的办法,包括图像的翻转,缩放,旋转和剪裁,重点在对代码的调用以此来达到自己的目的,相信读到这里的朋友们应该可以熟练的使用本文所介绍的几个函数以及它们的参数咱们调整变为适合你们自己的。当然代码并不能够解决所有关于图片的问题,有好想法的兄弟们也欢迎在评论区交流。

  • 8
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值