A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

图像裁剪

让我们使用选择行和列范围的方法从图像中提取更大的部分。这也称为裁剪图像。

让我们这次使用不同的图片。让我们看看它的样子。



  • >> img = imread('bicyle.png');



  • >> imshow(img);


Ok,那里有经典的两轮车。

我们先来检查一下图像的大小。

>> disp(size(img));

好的,320*500。

裁剪此图像时,我们希望我们的限制在此范围内。

假设我们想要选择行110到310以及列10到160。



  • >> cropped = img(110:310, 10:160);



  • >> imshow(cropped);


那是前轮。没有意义。

那么裁剪图像的大小是多少?

和以前一样,让我们使用size函数。

>> disp(size(cropped));

好的,201*151。

但这那令人惊讶吗?为什么不是200×150呢?

我们回顾一下从310到160的范围。注意,在这两个范围内,限制都是包括在内的。

这就是为什么第一个范围,从110到310,包含201个不同的行。同样,10到160包含151个不同的列。

尝试提取图像的不同部分。当您选择的范围超出范围时会发生什么。我们尝试运行如下代码:

>> corrped=img(20:400,10:32)

提示执行异常,因为x轴超过了限制范围。

颜色通道

我们看一下彩色图像怎么样?让我们来看看:



  • >> img = imread('fruit.png');



  • >> imshow(img);


您认为这张图片的大小是多少?

>> disp(size(img));

结果显示:258      320      3

为什么有三个数字?

前两个是高度和宽度。

第三个是图像中的多个颜色平面或通道,即三个。

那么你如何选择一个颜色的平面呢?我们将使用我们用于裁剪图像的相同索引表示法。

假设我们要选择红色通道,它位于索引1。我们想要所有行,所有列,但只需要第一个平面。

>> img_red = img(:, :, 2);

代码运行结果:

这就是红色通道的样子。较亮的区域表示红色值较高,较暗的区域则相反。苹果并不像你期望的那么明亮。

我们看看这个图片的大小:

>> disp(size(img_red));

代码运行结果:258      320

正如所料,颜色通道的宽度和高度与原始图像相同,但它没有第三个尺寸。

嗯,这是有道理的,不是吗?该颜色平面是三个中的一个,它们堆叠在一起以创建彩色图像。

它们中的每一个都是二维阵列。请注意,提取的颜色通道本身就是一个图像,因此您可以应用之前看到的相同操作。

让我们尝试绘制图像中一行的值。

>> plot(img_red(150, 0));

运行代码结果:

这就是图的样子。

在代码编辑器中使用此图像,尝试不同的操作,尝试选择其他彩色通道。

图像相加

那么对图像的算术运算是什么样的呢?让我们从添加两个图像开始。

像以前一样,我们加载图像。



  • >> dolphin = imread('dolphin.png');



  • >> dolphin = imread('bicycle.png');


运行代码结果:

还要显示它们并确保它们的尺寸相等。



  • >> imshow(dolphin);



  • >> disp("Dolphin image size:");



  • >> disp(size(dolphin));







  • >> imshow(bicycle);



  • >> disp("bicycle image size:");



  • >> disp(size(bicycle));


运行代码结果:

正如我们在程序输出看到的那样, 它们大小相等。这很重要,因为添加的是元素操作的元素。

这意味着一个图像中的像素与相应的像素相加称为另外一个图像。

由于两个图像大小相同,我们可以添加它们。



  • >> dolphin = imread('dolphin.png');



  • >> bicycle = imread('bicycle.png');







  • >> summed = dolphin + bicycle;



  • >> imshow(summed)


Octave足够智能,可以发现这两个是矩阵相同的大小,因此执行元素添加。运行结果是:

正如你所料,一个包含两个源图像元素的图像。你可以清楚地看到自动车和白色冲浪。你还可以隐约看到海豚。

注意这个图像是非常明亮的。导致许多区域看不到了。

为什么图像会这么的明亮呢?

为了找到答案,让我们回顾一下我们的代码。

请注意,我们直接从两个图像中添加值。两个图像都很明亮的区域变得更加明亮。

这表明我们应该缩小图像强度值。但是要调整多少呢?

我们会想到一个像素,这两个图像都具有最大强度值。求和图像中的像素将具有最大值的两倍。

因此,如果我们想要求和图像中的最大可能值,与每个源图像中的最大可能值相同,那么我们想把强度除以2。



  • >> dolphin = imread('dolphin.png');



  • >> bicycle = imread('bicycle.png');







  • >> average = dolphin / 2 + bicycle / 2;



  • >> imshow(average);


这看起来熟悉吗?是的,这是两张图片的平均值。让我们看看这是什么样的:

Ok,好多了。将此与直接总和相比较:

你可以清楚地看到亮度的差异。另外注意,不再有任何褪色区域。让我们重写平均值的表达式,看看会发生什么。

我们先将两个源图像相加,再去除以2:



  • >> dolphin = imread('dolphin.png');



  • >> bicycle = imread('bicycle');







  • >> average = dolphin / 2 + bicycle / 2;



  • >> imshow(average);







  • >> average_alt = (dolphin + bicycle) / 2;



  • >> imshow(average_alt);


让我们看看运行后的结果:

嗯?这不对呀!这两个结果怎么不一样呢??

解决这个问题的关键是知道这两个图像都是Uint8类型。

这意味着所有像素值都是0到255范围内的整数。

由于图像是无符号整数,Octave尝试在整个算术运算中保留相同的数据类型。

所以183除以2出来是92。请注意,Octave舍入到最接近的整数。它正在四舍五入

同样地,152除以2是76,它们的总和是168。

在第二种情况下,首先执行添加,因此183加152是335。

但请注意,此数字不适合无符号整数8位范围。

Uint8最大值为255。所以这个数字被截断到上限。除法按预期进行,结果为128。

您可以想象,在许多地方,像素值总计超过255。在所有这些位置,结果只会得到128。这通常小于两个数字的实际平均值。

因此,我们看到第一种方法更好地保留了像素值。

你肯定会遇到这些奇怪的算术错误。请注意您使用的图像数据类型以及执行算术运算的顺序。


1 个回复

倒序浏览
奈斯
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马