深度学习的图像盲几何畸变校正‘Blind Geometric Distortion Correction on Images Through Deep Learning(CVPR 2019)‘ 复现

代码:GitHub - GeoProj

1)创建环境:

conda create -n GeoProj python=3.8

2)进入并配置环境:

conda activate GeoProj

代码没给requirements.txt,自己总结了一个,如下:

torch
tensorflow
numpy
scikit-image
argparse
scipy
logger
torchvision
opencv-python

然后终端配置环境:

pip install -r requirements.txt

注意:1) pip install 所需包时,把梯子关了,不然pip会失败。 

           2) 若 pip install tensorflow 太慢,可以加镜像,会好很多:

pip install tensorflow -i https://pypi.tuna.tsinghua.edu.cn/simple

3)数据集的选取与准备:

        由于是用自己电脑跑的,内存有限。于是随便找了个猫狗数据集,一共2200张图片。将所有图片都一起放到source_ad文件夹内,用来保存原始图片,然后我写了一个adjustment.py工具,这段代码遍历指定文件夹中的所有图片,如果图片的长和宽有一个不大于512像素,脚本会首先将图片等比例放大两倍,然后再次检查其尺寸。如果放大后的图片的长和宽均大于512像素,脚本将从图片的中心位置截取一个512x512像素的区域并保存。新图片将按照"000000.jpg"的格式依次命名。(以上要求为满足模型所需数据集要求)

adjustment.py

import os
from PIL import Image

def process_and_save_images(source_folder, destination_folder, target_size=(512, 512)):
    # Ensure the destination folder exists
    if not os.path.exists(destination_folder):
        os.makedirs(destination_folder)
    # Initialize a counter for naming the images
    counter = 0
    # Iterate over all files in the source folder
    for filename in os.listdir(source_folder):
        # Check if the file is an image
        if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.tiff')):
            filepath = os.path.join(source_folder, filename)
            with Image.open(filepath) as img:
                # If both dimensions are not larger than 512, enlarge the image by 2 times
                while img.width <= target_size[0] or img.height <= target_size[1]:
                    img = img.resize((img.width * 2, img.height * 2), Image.Resampling.LANCZOS)

                # Check if both dimensions are larger than 512 after enlargement
                if img.width > target_size[0] and img.height > target_size[1]:
                    # Calculate the center crop box
                    left = (img.width - target_size[0]) / 2
                    top = (img.height - target_size[1]) / 2
                    right = (img.width + target_size[0]) / 2
                    bottom = (img.height + target_size[1]) / 2
                    img_cropped = img.crop((left, top, right, bottom))
                    # Create a new filename
                    new_filename = '{:06d}.jpg'.format(counter)
                    new_filepath = os.path.join(destination_folder, new_filename)
                    # Save the cropped image
                    img_cropped.save(new_filepath, 'JPEG')
                    # Increment the counter
                    counter += 1

# Example usage
source_ad_folder = '/source_ad'  # Replace with your source_ad folder path
source_folder = '/source'  # Replace with your source folder path

# Resize and save the images
process_and_save_images(source_ad_folder, source_folder)

 原始数据集如图:


4)模型训练数据集生成:

生成数据集
为了使用提供的代码训练模型,需要以一定的方式生成数据。

方法一:直接在编译时修改

python data/dataset_generate.py [--sourcedir [PATH]] [--datasetdir [PATH]] 
                                [--trainnum [NUMBER]] [--testnum [NUMBER]]

--sourcedir       Path to original non-distorted images     # 原始非失真图像的路径
--datasetdir      Path to the generated dataset             # 生成数据集的路径
--trainnum        Number of generated training samples      # 生成的训练样本数
--testnum         Number of generated testing samples       # 生成的测试样本数

方法二:修改data/dataset_generate.py文件

(由于发现用Windows实现2200张数据集生成实在太慢,所以设置trainnum为100,testnum为20)。 

然后直接:

python data/dataset_generate.py

开始创造:

one year later~~~~~

运行很久之后报错了:

pincushion True 0
Traceback (most recent call last):
  File "E:\BRI_of_ZJU\GeoProj\data\dataset_generate.py", line 166, in <module>
    generatepindata(types, k, trainFlag = True)
  File "E:\BRI_of_ZJU\GeoProj\data\dataset_generate.py", line 115, in generatepindata
    padImg[0:height, 0:width, :] = ScaImg[0:height, 0:width, :]
ValueError: could not broadcast input array from shape (256,256,2) into shape (256,256,3)

但是经过检查所有图片都是三通道的。经过研究发现在使用 rescale 函数后图像从三通道变成了两通道,这可能是由于 rescale 函数的行为与图像的数据类型有关。一个替代方法是直接使用 PIL 库进行缩放,它通常能更好地保持图像的原始属性。对代码进行修改:

from PIL import Image

# ... 其他代码 ...

OriImg = io.imread('%s%s%s%s' % (args.sourcedir, '/', str(k).zfill(6), '.jpg'))
# print("Original Image Shape:", OriImg.shape)  # 打印原始图像形状

# 使用PIL进行缩放
pil_img = Image.fromarray(OriImg)
scaled_img = pil_img.resize((int(pil_img.width * 0.5), int(pil_img.height * 0.5)), Image.Resampling.LANCZOS)

# 转换回numpy数组
ScaImg = np.array(scaled_img)
# print("Scaled Image Shape:", ScaImg.shape)  # 打印缩放后图像形状

# ... 后续处理 ...

修改后成功生成数据集。

 


5)开始训练:

1. 训练GeoNetS

        将代码中的路径更改为自己的路径。

运行报错了:
Traceback (most recent call last):
  File "trainNetS.py", line 77, in <module>
    logger = Logger('./logs')
  File "E:\BRI_of_ZJU\GeoProj\logger.py", line 15, in __init__
    self.writer = tf.summary.FileWriter(log_dir)
AttributeError: module 'tensorboard.summary._tf.summary' has no attribute 'FileWriter'

发现是tensorflow版本的问题,将tf.summary.FileWriter()换成tf.summary.create_file_writer(),以及其他问题进行了修改,代码如下。

    def __init__(self, log_dir):
        """Create a summary writer logging to log_dir."""
        self.writer = tf.summary.create_file_writer(log_dir)

    def scalar_summary(self, tag, value, step):
        """Log a scalar variable."""
        with self.writer.as_default():
            tf.summary.scalar(tag, value, step=step)
            self.writer.flush()

解决问题! 

然后遇到了尴尬的问题,我的电脑CUDA显存不足:
torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate 512.00 MiB (GPU 0; 4.00 GiB total capacity; 3.13 GiB already allocated; 0 bytes free; 3.14 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation.  See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF

好吧,那只能放到服务器上跑了~ 显卡有限,采用单卡训练。

CUDA_VISIBLE_DEVICES=1 python trainNetS.py

训练完毕。


2. 训练GeoNetM

        根据个人情况修改代码。

 CUDA_VISIBLE_DEVICES=2 python trainNetM.py

保存训练好的模型。 


6)评估模型:

原作者提供的训练好的模型:需要梯子,我下载好放到了文件夹内。

geoProjModels.zip - Google 云端硬盘

可以使用原作者提供的模型,也可以用自己训练的。 

根据自己的需求修改eval.py,注意这个k的取值按图片编号修改。 

由于我还想看到矫正后的图片,所以我在最后增加了一些代码用来保存纠正后的图片:

        # Load the .mat file that contains the distortion maps
        mat_contents = scio.loadmat(saveMatPath)

        # Load the image that you want to correct
        image = cv2.imread(imgPath)
        h, w = image.shape[:2]
        x, y = np.meshgrid(np.arange(w), np.arange(h))

        # Retrieve the u and v displacement maps from the .mat file
        u = mat_contents['u']
        v = mat_contents['v']

        corrected_image = cv2.remap(image, (x - u).astype(np.float32), (y - v).astype(np.float32), cv2.INTER_LINEAR)

        # Save the corrected image to a file
        cv2.imwrite('%s%s%s%s%s%s' % (saveimgPath, '/',types,'_', str(k).zfill(6), '.jpg'), corrected_image)

运行,并保存结果。

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
geometric modeling based on polygonal meshes (基于多边形网格的几何建模)是一种常用的三维建模方法,主要用于创建、编辑和操作多边形网格模型。该方法使用一系列的顶点、边和面来描述物体的几何结构。 这种建模方法的代码实现包括以下几个关键步骤。首先,通过读取或创建输入的多边形网格数据,包括顶点坐标和面的连接信息。接下来,进行模型的编辑和操作,比如移动顶点、调整边和面,或者添加删除顶点、边和面。在编辑过程中,还可以进行细分、合并、镜像、变形等操作,以获得更复杂的几何形状。 在编辑完成后,多边形网格模型可以进行进一步的处理和优化。例如,进行曲面重建以得到光滑的几何表面,进行材质和纹理的贴图,或者进行拓扑结构优化以减少模型的面数和存储空间。 在代码实现中,需要使用适当的数据结构来表示多边形网格,比如使用数组、链表或树等方式存储顶点、边和面的信息。同时,还需要实现各种编辑和操作的算法,如移动、旋转、缩放等,以及模型处理和优化的算法。 此外,为了提高建模效率和减少计算复杂度,可以使用一些优化技术,如边缘塌陷、局部细分、空间划分等,来提高代码性能和减少内存占用。 综上所述,geometric modeling based on polygonal meshes的代码实现涉及了多个关键步骤和算法,以实现对三维模型的创建、编辑和优化。这种方法在计算机图形学、虚拟现实、游戏开发等领域得到广泛应用,为我们提供了强大而灵活的三维形状建模工具。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程日记✧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值