Engee 文档
Notebook

图像处理

在本例中,我们将演示如何将Engee应用于图像处理,分解图像处理的各个功能,了解如何访问图像以及如何处理和表示图像。

首先,让我们选择所需的函数库。

In [ ]:
Pkg.add(["ImageShow"])
In [ ]:
using Images # Библиотека обработки изображений
using ImageShow # Библиотека отрисовки изображений

加载图像

使用 load 功能可以将图像以矩阵形式保存到工作区。

In [ ]:
I = load("/user/start/examples/image_processing/processing_methods/IMG_001.jpg")
Out[0]:
No description has been provided for this image

将 RGB 转换为灰度

让我们创建一个自定义函数,用于计算三维 RGB 矩阵测量值总和的平均值。

RGB(红、绿、蓝)是一种加色模型,它描述了使用三种颜色(通常称为三原色)进行色彩还原的编码方式。

In [ ]:
function brightness(pixel)
    arr = pixel.r + pixel.g + pixel.b;
    return sum(arr) / length(arr)
end
Out[0]:
brightness (generic function with 1 method)

定义完函数后,让我们调用它并渲染图像。

In [ ]:
Ibright = brightness.(I)
simshow(Ibright)
Out[0]:
No description has been provided for this image

如上图所示,我们已将图像还原为灰色。

边角检测

边角检测试图识别图像中位置明确的点,这些点可以在同一场景的多幅图像中进行可靠标注。这些点通常位于图像对象的边角或边缘,因此该方法也被称为边角检测。

边角检测在许多计算机视觉任务中都很有用,如图像配准、运动检测和全景拼接。该方法基于这样一个事实:如果已知两幅不同图像中相同点的位置,就有机会对齐这些图像。

对于角落检测,我们将使用 imcorner 函数,该函数有一个附加参数,即用于检测感兴趣点的阈值百分比参数。

In [ ]:
corners = imcorner(Ibright, Percentile(98.5));
┌ Error: handle_connection handler error
│   exception = (Base.IOError("write: broken pipe (EPIPE)", -32), Base.StackTraces.StackFrame[uv_write(s::TCPSocket, p::Ptr{UInt8}, n::UInt64) at stream.jl:1064, unsafe_write(s::TCPSocket, p::Ptr{UInt8}, n::UInt64) at stream.jl:1118, unsafe_write(c::HTTP.ConnectionPool.Connection, p::Ptr{UInt8}, n::UInt64) at ConnectionPool.jl:106, write(io::HTTP.ConnectionPool.Connection, s::String) at io.jl:244, write at io.jl:676 [inlined], unsafe_write(http::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.ConnectionPool.Connection}, p::Ptr{UInt8}, n::UInt64) at Streams.jl:96, write(io::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.ConnectionPool.Connection}, s::String) at io.jl:244, write(io::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.ConnectionPool.Connection}, s::Base.CodeUnits{UInt8, String}) at basic.jl:758, (::HTTP.Handlers.var"#1#2"{HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}})(stream::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.ConnectionPool.Connection}) at Handlers.jl:61, #invokelatest#2 at essentials.jl:729 [inlined], invokelatest at essentials.jl:726 [inlined], handle_connection(f::Function, c::HTTP.ConnectionPool.Connection, listener::HTTP.Servers.Listener{Nothing, Sockets.TCPServer}, readtimeout::Int64, access_log::Nothing) at Servers.jl:447, (::HTTP.Servers.var"#16#17"{HTTP.Handlers.var"#1#2"{HTTP.Handlers.Router{typeof(HTTP.Handlers.default404), typeof(HTTP.Handlers.default405), Nothing}}, HTTP.Servers.Listener{Nothing, Sockets.TCPServer}, Set{HTTP.ConnectionPool.Connection}, Int64, Nothing, Base.Semaphore, HTTP.ConnectionPool.Connection})() at task.jl:484])
└ @ HTTP.Servers /root/.julia/packages/HTTP/Kxa7P/src/Servers.jl:461

检测到兴趣点后,我们会将灰度图像转换为 RGB 图像,并为兴趣点处的第一个矩阵测量值赋予单位值,从而将其标记为红色。

In [ ]:
img_copy = RGB.(Ibright)
img_copy[corners] .= RGB(1.0, 0.0, 0.0)
Out[0]:
No description has been provided for this image
┌ Warning: Output swatches are reduced due to the large size (1×29420).
│ Load the ImageShow package for large images.
└ @ Colors /root/.julia/packages/Colors/mIuXl/src/display.jl:159

我们可以看到,角点是在图像中对比度最大的物体上发现的。在本例中,这些物体就是云和海。

In [ ]:
simshow(img_copy) 
Out[0]:
No description has been provided for this image

检测描绘对象的边界

图像处理中的另一项常见任务是寻找物体的边界。为此,我们可以使用Kernel.sobel函数,它可以将图像转换到频域。下面我们将介绍一个自定义的边界检测函数。

In [ ]:
function find_energy(image)
    energy_y = imfilter(brightness.(image), Kernel.sobel()[1])
    energy_x = imfilter(brightness.(image), Kernel.sobel()[2])    
    return sqrt.(energy_x.^2 + energy_y.^2)
end
Out[0]:
find_energy (generic function with 1 method)

接下来,让我们将自定义边界检测函数应用于原始图像,并显示图像处理的结果。

In [ ]:
simshow(find_energy(I))
Out[0]:
No description has been provided for this image

根据处理结果,我们可以明确地确定图像中每个物体的边界,这些数据随后可用于进一步的图像处理。

输出

正如我们处理图片的示例所示,Engee 非常适合图像处理。鉴于该环境具有广泛的数学功能,我们可以使用自定义函数来描述任何特定的处理算法。