这学期修了一门数字图像处理的课程,虽然深度学习已经在CV领域大行其道,但是最基础的图像处理也同样需要掌握,通过这门课程,能够弥补一些图像处理的不足,这门课的作业主要会用一些matlab,python和opencv的东西。
作业一
part1
读取一张color map image,将其转换成true color image,并保存为一张jpg图片。
Algorithm
color-map image本质上就是将一张图片存成两个部分,第一个部分是一个图片大小的矩阵I,第二个部分是一个color map查找表,一般是$m \times 3$,m表示color map的维度,将矩阵I中每个数字在color map中找到,然后将其替换成对应的那一行RGB即可,只是注意color map中是$0 \thicksim 1$的double类型,需要乘上255并将其变成uint8类型。
Implement and Result
将color map image 转换为ture image的代码如下
function [real_img ] = transformTrueimage(img, cmap)
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
[height, width] = size(img);
real_img = zeros(height, width, 3);
for i = 1:height
for j = 1:width
idx = img(i, j) + 1;
real_color = cmap(idx, :) * 255.0;
real_img(i, j, :) = real_color;
end
end
real_img = uint8(real_img);
end
文件在assignment1/hw1/transfromTrueimage.m
中,运行/assignment1/hw1/test_true.m
能够得到两张图片的对比,第一张为color map image,第二张为true image,最后true iamge保存为hw1_true.jpg
,test_true.m
的代码如下
clear;
clc;
[cimg, cmap] = imread('./hw1.bmp', 'bmp');
true_img = transformTrueimage(cimg, cmap);
imwrite(true_img, 'hw1_treu.jpg');
figure;
image(cimg);
colormap(cmap);
title('color map image');
figure;
image(true_img);
title('true image');
Discussion
这就是一个简单的重新映射的过程,得到的图片之间不会有什么差别。
part2
设计算法将一张true color image转换成color-map image,并尽可能保留原始颜色信息。color map image的colormap维度为256。
Algorithm
读入一张图片I,图片的size是$m \times n \times 3$,那么将每一个像素点取出来就能够得到一个color map索引表,大小是$m*n \times 3$,一般来说m*n都是远远大于256,所以需要设计一个算法来降低维度。
这里我们想到的算法是聚类算法k-means,一共有$m * n$个数据点,每个数据点都是三维的,我们希望能够将他们分成256类,这样我们就能够将ture image中所有的像素点分到这256类上,而这256类就是我们生成的color map索引表。
对于kmeans算法,假设原始数据点是${x_1, x_2, \cdots, x_n}$,我们希望将他们分成k类,首先我们随机初始化k个中心点$u_1, u_2, \cdots, u_k$,那么实现依赖于不断迭代下面公式(1)和(2)。
$$
c^{(i)} = \mathop{arg min}j || x^{(i)} - u_j|| ^ 2
$$
$$
u_j = \frac{\sum{i=1}^m 1{c^{(i)}=j} x{(i)}}{\sum_{i=1}m 1{c^{(i)} = j}}
$$
公式(1)是说对于每个数据点,每次都找离其最近的中心点,并将其标记为该类,公式(2)是说使用该类所有点的重心作为这一类新的中心点。
使用kmeans算法得到了color map之后,我们就可以将ture image中每个像素点对应于color map中的一个值,这样就得到了color map image。
Implement and Result
kmeans的算法实现如下
function [ u, c ] = KMeans( x, k )
%Implement of Keans Algorithm for cluster colormap image
% x is a n-dimentional data, and k means how many centers of the cluster
[m, n] = size(x);
u = zeros(k, n);
% initialize kmeans center using random uniform cutting min to max
sort_x = sort(x, 1);
min_value = sort_x(1, :);
max_value = sort_x(m, :);
for i = 1 : k
u(i, :) = min_value + (max_value - min_value) .* rand();
end
c = zeros([m, 1]);
last_error = 0;
% iter two formula to converge
while 1
total_error = 0;
% fisrt formula
for i = 1 : m
min_dist = sum((x(i, :) - u(1, :)) .^ 2);
c(i) = 1;
for j = 1 : k
temp_dist = sum((x(i, :) - u(j, :)) .^ 2);
if temp_dist < min_dist
min_dist = temp_dist;
c(i) = j;
end
end
total_error = total_error + min_dist;
end
if abs(total_error - last_error) < 1
break
end
last_error = total_error;
% second formula
for i = 1 : k
temp_u = zeros([1, n]);
count = 0;
for j = 1 : m
if c(j) == i
temp_u = temp_u + x(j, :);
count = count + 1;
end
end
if count == 0
u(i, :) = min_value + (max_value - min_value) .* rand();
else
u(i, :) = temp_u ./ count;
end
end
end
使用test_kmeans.m
来测试了kmeans算法,随机生成三组随机点,然后使用kmeans将其分成三个聚类。
然后得到color map image的实现如下
function [ colormap_img, new_cmap ] = transformColormap( img, colormap_dim )
%UNTITLED3 Summary of this function goes here
% Detailed explanation goes here
[height, width, channel] = size(img);
cmap = zeros(height * width, 3);
for i = 1 : height
for j = 1 : width
cmap((i - 1) * width + j, :) = double(img(i, j, :)) / 255;
end
end
[new_cmap, c] = KMeans(cmap, colormap_dim);
colormap_img = zeros([height, width]);
for i = 1 : height
for j = 1 : width
colormap_img(i, j) = c((i - 1) * width + j);
end
end
end
最后使用test_colormap.m
来测试true image和color map image,先生成两张图片进行肉眼对比,然后使用第一个作业中的函数将color map image再转换回ture image进行误差对比。
上面一张是true image,下面一张是color map image。
Discussion
通过肉眼我们发现转换成了color map iamge之后,与true image之间的对比不存在太多的误差,同时我设计了一个误差指标,将两幅图每个像素点进行对比,然后取绝对值求和,再除以像素点的总数,这样可以得到平均每个像素点的偏差,最后得到error大约是1.4,说明每个像素点的偏移是比较小的,这也说明了转换之后信息保留得非常多。
作业二
part1
解释图像直方图均衡化原理,并用程序实现。
Algorithm
对于每张读入的图片,可以统计每一个数值的频率形成直方图,其直方图可能会呈现分布不均匀的情况,这样就使得图片没有太高的对比度,而图像直方图均衡化可以对图片中像素个数多的像素级进行展宽,对像素个数少的灰度级进行压缩,从而扩展了图片原取值范围,提高对比图,使得图片更加清晰。
Implement and Result
图像直方图的实现如下
function h = compute_hist( img )
%compute histogram of an image
[m, n, c] = size(img);
h = zeros([256, c]);
for i = 1 : 256
h(i, :) = sum(sum(img == (i - 1)));
end
end
均衡化的算法实现如下
function [ h, lut, eq_I] = HistogramEqualization( I )
%HistogramEqualization
% compute histogram of an image and do histogram equalization
[m, n, c] = size(I);
h = compute_hist(I);
[m_h, n_h] = size(h);
total = sum(h);
% construct lut
lut = zeros([m_h, n_h]);
lut(1, :) = h(1, :) ./ total;
for i = 2 : m_h
lut(i, :) = lut(i - 1, :) + h(i, :) ./ total;
end
for i = 1 : m_h
lut(i, :) = round(lut(i, :) .* 255);
end
eq_I = zeros(size(I));
for i = 1 : m
for j = 1 : n
for k = 1 : c
eq_I(i, j, k) = lut(I(i, j, k) + 1, k);
end
end
end
eq_I = uint8(eq_I);
end
使用test_eq_hist.m
来测试均衡化效果,下面是直方图和均衡化之后的图片。
Discussion
可以发现均衡化之后的图片,直方图变得更加的均匀,同时图片也有了更高的对比度。
part2
输入图片A与参考图片R,对A做变换得到A',使得其统计直方图尽可能与R的统计直方图接近。
Algorithm
两张图片的直方图不可能完全一样,但是我们可以通过匹配分位数来实现两幅图直方图的匹配,对于输入图片I,对于每个像素点,我们先计算出其积累概率函数,然后在参考图片中寻找与这个积累概率函数最接近的像素点,然后将原图片的像素点替换成这个像素点即可,对于给出的输入图片和参考图片,我们可以构造一个查找表方便计算。
Implement and Result
图片匹配的程序如下
function [ K ] = HistogramMatching( I, target )
%UNTITLED8 Summary of this function goes here
% Detailed explanation goes here
I_h = compute_hist(I);
total_I = sum(I_h);
target_h = compute_hist(target);
total_target = sum(target_h);
[m, n] = size(I_h);
% define pdf for image I
pdf_h = zeros([m, n]);
pdf_h(1, :) = I_h(1, :) ./ total_I;
for i = 2 : m
pdf_h(i, :) = pdf_h(i - 1, :) + I_h(i, :) ./ total_I;
end
% define pdf for image target
pdf_target = zeros([m, n]);
pdf_target(1, :) = target_h(1, :) ./ total_I;
for i = 2 : m
pdf_target(i, :) = pdf_target(i - 1, :) + target_h(i, :) ./ total_target;
end
%define LUT for image transform with target
LUT = zeros([m, n]);
for i = 1 : 256
for k = 1 : 3
temp = pdf_h(i, k);
for j = 1 : 256
if pdf_target(j, k) > temp
LUT(i, k) = j;
break;
end
end
end
end
% get new image close to target image
K = zeros(size(I));
[r, g, b] = size(K);
for i = 1 : r
for j = 1 : g
for c = 1 : b
K(i, j, c) = LUT(I(i, j, c) + 1, c);
end
end
end
K = uint8(K);
end
使用test_match.m
来测试匹配效果,输入两张图片,得到他们的直方图表示,然后进行图片匹配,将匹配的新图片直方图显示出来进行比较。下图就是所有的结果。
2.jpg 3.jpg 4.jpg 5.jpg 6.jpg
Discussion
可以发现进行匹配之后,图片的色调有了明显的变化,同时根据直方图我们也能够看出原始图片更向参考图片靠拢。
全部代码在github
网友评论