# Homework-1 **Repository Path**: original4422/Homework-1 ## Basic Information - **Project Name**: Homework-1 - **Description**: 2024年秋季学期《计算机视觉》课程第一次作业 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2024-09-19 - **Last Updated**: 2024-09-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Homework 1 对于第一次作业,我们只需了解一点代码库并练习简单的图像操作方法。 ## 目录 - [设置代码仓库](#设置代码仓库) - [下载编译代码](#下载编译代码) - [运行测试代码](#运行测试代码) - [图像操作基础](#图像操作基础) - [题目 1. 获取和设置像素](#题目-1-获取和设置像素) - [题目 2. 复制图像](#题目-2-复制图像) - [题目 3. 灰度化图像](#题目-3-灰度化图像) - [题目 4. 偏移图像颜色](#题目-4-偏移图像颜色) - [题目 5. 截断像素值](#题目-5-截断像素值) - [题目 6. RGB 转 HSV](#题目-6-rgb-转-hsv) - [题目 7. HSV 转 RGB](#题目-7-hsv-转-rgb) - [题目 8. 拓展作业 1(难度一般)](#题目-8-拓展作业-1难度一般) - [题目 9. 拓展作业 2(稍难一些)](#题目-9-拓展作业-2稍难一些) - [作业提交要求](#作业提交要求) ## 设置代码仓库 ### 下载编译代码 1. 下载代码:从 Gitee 克隆仓库。 ```bash git clone https://gitee.com/ghgxj/Homework-1.git ``` 2. 安装依赖:cmake和g++ - 对于Ubuntu和基于Debian的系统 ```bash sudo apt update sudo apt install cmake sudo apt install g++ ``` - 对于CentOS和Fedora系统 ```bash sudo yum install cmake sudo yum install gcc-c++ ``` --- 对于Ubuntu系统,亲测如下版本的cmake和g++可用: ```bash root@DESKTOP-3ORBLTV:~/Homework-1# cmake --version cmake version 3.22.1 CMake suite maintained and supported by Kitware (kitware.com/cmake). root@DESKTOP-3ORBLTV:~/Homework-1# g++ --version g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ``` 3. 编译代码:我们将使用 `cmake` 和 `make` 构建和编译库。这里,我们提供了一个 bash 脚本 [compile.sh](/compile.sh) 可以方便地为您完成此操作。建议使用 Linux 或 MacOS 来完成作业,因为设置 cmake 和 make 会更简单。 - Linux and MacOS ```bash ./compile.sh # runs cmake and make for you and produces ./test0, that is basically all you should need. ./clean.sh # cleans all files ./compile.sh # compiles again ``` - Windows 详见 [Windows 安装指南](README-Windows.md)。温馨提示:若目前手头只有windows系统的电脑,推荐安装 Linux 子系统(WSL),实测可用。 ### 运行测试代码 每次对代码进行任何更改时,请运行上述编译命令。我们提供了一个简单的测试程序来测试一些功能。然后您可以通过运行以下命令来快速测试您的更改 ```bash ./test0 ``` 如果运行上述代码而不对原始代码库进行任何更改,您将得到以下结果: ```bash 17 tests, 3 passed, 14 failed ``` 一旦一切都正确实施,您将得到: ```bash 17 tests, 17 passed, 0 failed ``` 请注意,通过所有测试并不能保证您的程序 100% 正确。我们将进行更广泛的测试。 ## 图像操作基础 我们有一个基本的 c++结构来存储库中的图像。`Image` 结构体存储图像元数据,如宽度、高度和通道数。它还包含作为浮点数组存储的图像数据。你可以在 [src/image.h](/src/image.h) 中查看它,它看起来像这样: ```cpp struct Image { int h,w,c; float *data; ....... }; ``` 如果您想创建一个维度为宽度 x 高度 x 通道的新图像,您可以定义: ```cpp Image im(w,h,c); ``` 该结构定义了所有必要的运算符,因此您可以复制、重新分配、作为函数的引用传递等: ```cpp Image im(5,6,7); Image im2=im; im=im2; void scramble_image(const Image& image); ``` 如果仅访问,则始终将图像作为 `const Image& image` 传递;如果要修改,则始终将图像作为 `Image& image` 传递。请参阅提供的代码以获取指导。 如果要访问像素,可以执行以下操作: ```cpp float value = im(0,2,1); // gets the pixel at column 0, row 2 and channel 1 im(3,0,2) = 0.76; // sets the pixel at column 3, row 0 and channel 2 ``` 如果指定越界坐标,则会出现错误。 我们还提供了一些用于加载和保存图像的功能。二进制格式可能会在课程的后期变得有用。使用任何函数(成员函数和独立函数)来加载新图像: ```cpp Image im = load_image("image.jpg"); im.load_image("another.png"); im.load_binary("binary.bin"); ``` 要保存图像,请使用: ```cpp im.save_image("output"); // save_image saves the image as a .jpg file im.save_png("output"); // save_png saves the image as a .png file im.save_binary("output.bin"); // save_binary saves as a raw binary file ``` 请随意探索 `image.h` 和 `struct Image {...}` 来熟悉上述操作。如果您对加载/保存的具体实现感兴趣,也可以浏览其他提供的文件。鉴于加载和保存图像很复杂,我们直接使用 `stb_image` 库来实现的。 ---
您将修改并只提交 `src/process_image.cpp` 和 `src/access_image.cpp` 两个文件。
--- ## 题目 1. 获取和设置像素 我们要做的最基本的操作是更改图像中的像素。我们将图像表示为 3 维张量。我们有空间信息以及多个通道,它们组合在一起形成彩色图像:  我们约定坐标系从图像的左上角开始,如下所示:  在我们的 `data` 数组中,我们以 `CHW` 格式存储图像。数据中的第一个像素位于通道 0、第 0 行、第 0 列(请注意,行对应于 Y 轴,列对应于 X 轴)。下一个像素是通道 0、第 0 行、第 1 列,然后是通道 0、第 0 行、第 2 列等。访问器运算符实际上需要像素值的地址 `data` `CHW` `image(1,2,1)` 您的第一个任务是在以下位置实现计算它的函数:[src/access_image.cpp](/src/access_image.cpp) ```cpp int pixel_address(const Image& im, int x, int y, int ch); ``` `pixel_address` 应返回像素值在数据数组中的 `x,y,ch` 位置。 请注意,对于像素访问,运算符 `()` 对于 `Image` 是重载(overloaded)的(请参见 `image.h`)。它将使用您的 `pixel_address` 函数来查找正确的像素位置。 尽管默认情况下,像素访问运算符 `image(1,2,1)` 会执行边界检查。但在某些情况下,如果我们采用填充策略而不用担心边界,则会更容易。这里有许多可能的填充策略:  我们将使用 `clamp` 填充策略。这意味着,如果程序员要求在列 -3 处提供像素,则使用列 0,或者如果他们要求列 300 并且图像仅为 256x256,您将使用列 255(因为从零开始的索引)。 你的第二个任务是在 [src/access_image.cpp](/src/access_image.cpp) 中实现下列两个函数: ```cpp float get_clamped_pixel(const Image& im, int x, int y, int ch); void set_pixel(Image& im, int x, int y, int c, float value); ``` 如果传入越界坐标(像素坐标大于宽度或高度,或小于零),`set_pixel` 应直接返回而不执行任何操作。 对于 `get_clamped_pixel`,我们将对图像进行填充。 请注意,你可以使用 `()` 操作符, 例如 `im(3, 2, 0)` 来访问像素。 我们可以通过移除所有红色通道来测试我们的像素设置代码对狗图片的效果。如果你愿意,可以创建一个类似于 `test0` 的新可执行文件,在其中可以使用你新编写的图像库进行探索。按照 `CMakeLists.txt` 和 `src/test/test0.cpp` 中的示例创建新的可执行文件。 ```cpp // 1-2. Getting and setting pixels Image im2 = load_image("data/dog.jpg"); for (int i=0; i