彩色图到灰度图究竟是怎么变换的

??之前对彩色图与灰度图仅仅停留在前者是3通道后者是单通道的理解上。我也知道计算机看图片是将它们当成数组,但是一直搞不清楚将一张彩色图转变为灰度图是怎么操作的。当然,很多库函数都提供借口,包括OpenCV、PIL等。这里我参考https://blog.csdn.net/saltriver/article/details/79677116 手动实现将一张彩色图转换为灰色图。当然还是以帅气的哈士奇.jpg作为我的练习对象,看到它敲代码都有动力。

from PIL import  Image
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
rgb_img = Image.open(‘Husky.jpg‘)
grey_img = rgb_img.convert(‘L‘)
rgb_img

grey_img

可以看到通过PIL的函数,可以轻松将图片转换为灰度图。

这里的哈士奇照片实在太大了,将它变得小一些。

rgb_img.thumbnail((800, 800))
grey_img.thumbnail((800, 800))
rgb_img

grey_img

最终的效果应该变为类似上面这张灰度图

# 获取彩色图的数据
rgb_arr = np.array(rgb_img)
# 窥探下这个数组,第一印象它是一个3维的
rgb_arr
array([[[ 93, 153, 203],
        [ 91, 151, 201],
        [ 90, 149, 200],
        ...,
        [  3, 120, 189],
        [  2, 119, 188],
        [  4, 121, 190]],

       [[ 90, 151, 200],
        [ 89, 150, 199],
        [ 90, 150, 200],
        ...,
        [  2, 119, 188],
        [  2, 119, 188],
        [  2, 119, 188]],

       [[ 86, 149, 196],
        [ 86, 149, 196],
        [ 89, 151, 198],
        ...,
        [  1, 119, 188],
        [  1, 119, 188],
        [  1, 118, 187]],

       ...,

       [[ 24,  22,  24],
        [ 25,  22,  24],
        [ 29,  26,  26],
        ...,
        [ 10,   9,  14],
        [  9,   8,  13],
        [  6,   5,  10]],

       [[ 23,  24,  28],
        [ 27,  28,  32],
        [ 44,  45,  48],
        ...,
        [ 10,   9,  14],
        [  7,   6,  11],
        [  6,   5,  10]],

       [[ 38,  41,  47],
        [ 50,  53,  59],
        [ 64,  66,  71],
        ...,
        [  8,   7,  12],
        [  6,   5,  10],
        [  7,   6,  11]]], dtype=uint8)
# 行 列 通道
rgb_arr.shape
(633, 800, 3)
# 宽(列数) 高(行数)
rgb_img.size
(800, 633)
# 可以用matlibplot.pyplot将数组显示为图片
plt.imshow(rgb_arr)
<matplotlib.image.AxesImage at 0x110cb71d0>

接下来对数组进行操作,第一种想法是将3个通道的数据取平均。

那么不禁要问,三个通道的数据是哪些?其实这也是我之前一直有些疑惑的地方。

x = rgb_arr[0][0]
# x代表图片中的1个像素点,它的颜色由[93, 153, 203]表示,因此这3个值为3个通道的值
x
array([ 93, 153, 203], dtype=uint8)
# 那么不难想象,可以通过两个for循环对这些值取平均
grey_arr = np.zeros(rgb_arr.shape[0:2])

# grey_arr.shape (633, 800)

for row in range(633):
    for col in range(800):
        grey_arr[row][col] = (int(rgb_arr[row][col][0]) + int(rgb_arr[row][col][1]) + int(rgb_arr[row][col][2])) / 3
grey_arr = np.array(grey_arr, dtype=np.uint8)
grey_arr
array([[149, 147, 146, ..., 104, 103, 105],
       [147, 146, 146, ..., 103, 103, 103],
       [143, 143, 146, ..., 102, 102, 102],
       ...,
       [ 23,  23,  27, ...,  11,  10,   7],
       [ 25,  29,  45, ...,  11,   8,   7],
       [ 42,  54,  67, ...,   9,   7,   8]], dtype=uint8)
out_img = Image.fromarray(grey_arr)
out_img

std_grey_arr = np.asarray(grey_img)
std_grey_arr
array([[140, 138, 136, ...,  92,  91,  93],
       [138, 137, 137, ...,  91,  91,  91],
       [135, 135, 137, ...,  91,  91,  90],
       ...,
       [ 22,  22,  26, ...,   9,   8,   5],
       [ 23,  27,  45, ...,   9,   6,   5],
       [ 40,  52,  66, ...,   7,   5,   6]], dtype=uint8)

自行生成的数据和通过借口函数转换得到的标准灰度图的数据还是有一定差距,

## 通过给定不同权重的方法再试一次

for row in range(633):
    for col in range(800):
        grey_arr[row][col] = 0.11 * rgb_arr[row][col][0] + 0.59 * rgb_arr[row][col][1] + 0.3 * rgb_arr[row][col][2]
grey_arr = np.array(grey_arr, dtype=np.uint8)
grey_arr
array([[161, 159, 157, ..., 127, 126, 128],
       [158, 157, 158, ..., 126, 126, 126],
       [156, 156, 158, ..., 126, 126, 125],
       ...,
       [ 22,  22,  26, ...,  10,   9,   6],
       [ 25,  29,  45, ...,  10,   7,   6],
       [ 42,  54,  67, ...,   8,   6,   7]], dtype=uint8)
out_img = Image.fromarray(grey_arr)
out_img

以上就是手动实现将RGB图片转为灰度图的过程,注意图片的数值类型为unit8

原文地址:https://www.cnblogs.com/shayue/p/10393542.html

时间: 2024-10-09 13:19:22

彩色图到灰度图究竟是怎么变换的的相关文章

Java 彩色图转灰度图

1. 方法1 BufferedImage grayImage = new BufferedImage(width, height, colorImage.TYPE_BYTE_GRAY); Graphics g = grayImage.getGraphics(); g.drawImage(colorImage, 0, 0, null); g.dispose(); 2. 方法2(不推荐) ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRA

Inkscape svg彩色图转灰度图

操作: Ctrl+A 全选所有对象, 然后使用滤镜渲染成灰度图, 至于这个RGB比值, 看个人需求, 标准情况下rgb2gray是0.299 * R + 0.587 * G + 0.114 * B 原始RGB图 灰度图 补: 如若只想快速预览灰度图的效果, 可View(视图) -> Color display mode(色彩显示模式) -> Gray(灰度) 原文地址:https://www.cnblogs.com/ZhengPeng7/p/10286580.html

Unity Shaders and Effects Cookbook (2-4) 压缩和混合纹理贴图:使用灰度图存储插值信息

这一节看了几次才慢慢的读懂. 首先是这个灰度图,为什么叫灰度图,是因为 这个图片中的 R.G.B 存放的都是同一份数据,打开Unity 来调一下颜色看看 更直观. 可以看到,当 R.G.B 三个值相同的时候,图片是只有黑白,而丢失了其它的颜色的,所以我们叫灰度图. 什么时候用到灰度图? 本文转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn 比如说高度图,在这个坐标的点,海拔高,就记作 1,海拔低就记作0 .把这一份数据 同时存储到

【OpenCV教程之九】平滑/模糊图片 Smooth / Blur Images及 彩色图转 灰度图和二值化

这一节,谈一谈如何对图像进行平滑,也可以叫做模糊.平滑图像的主要目的是减少噪声,这样采用平滑图像来降低噪声是是非常常见的预处理方法. 1.归一化滤波平滑-Homogeneous Smoothing 2.高斯滤波平滑-Gaussian Smoothing 3.中值滤波平滑-Median Smoothing 4.双边滤波平滑-Bilateral Smoothing 平滑是通过滑动窗口(内核或过滤器)扫描整个图像窗口,计算每个像素的基于核的值的和重叠的原始图像的像素的值的值来完成.这个过程在数学上称为

QImage Color Convert to Gray 转为灰度图

在Qt中,我们有时需要把QImage类的彩色图片转为灰度图,一开始我想的是用QImage的成员函数convertToFormat(),但是试了好多参数,返现转化的图片都有问题,不是我们想要的灰度图,如果谁用成员函数成功转化成了灰度图,请在评论区将您的方法写下,让博主学习一下.那么还有一种笨办法,就是手动将R,G,B的值平均一下,然后用平均值更新每一个像素值,也能得到灰度图.参见代码如下: // image is the input color image, img is output grey

S0.2 灰度图

目录 灰度图定义 灰度图优点 RGB转灰度算法(OpenCV3) 量化 算法公式 OpenCV自带函数实现 综合比较 灰度图定义 对于单色(灰度)图像而言,每个像素的亮度用一个数值来表示,通常数值范围在0到255之间,0表示黑.255表示白,其它值表示处于黑白之间的灰度. 灰度图优点 我们在进行很多图像的操作时,如果是彩色的 256 色图,由于图象处理后有可能会产生不属于这 256 种颜色的新颜色. RGB转灰度算法(OpenCV3) 量化 我们知道,自然界中的所有颜色都可以由红.绿.蓝(R,G

OprenCV学习之路一:将彩色图片转换成灰度图

//将一张彩色图片转成灰度图: //////////////////////////// #include<cv.h> #include<cvaux.h> #include<highgui.h> #include<ml.h> #include<iostream> using namespace std; using namespace cv; int main() { IplImage *src=0; src=cvLoadImage("

灰度图转彩色图(伪彩色处理)

将8Bit灰度数据转化为Bgr24的彩色图像 8bit灰度数据:byte[] GrayValue    长度:width * height PixelFormat pixelFormat = PixelFormats.Bgr24; byte[] colorvalues = GrayToColor(GrayValue); ByteSize = Width * Height; IntPtr dataPtr = IntPtr.Zero; GCHandle _hObject = GCHandle.All

怎么样用opencv将彩色图片转化成像素值只有0和255的灰度图?

  分类: OpenCV [Q1]怎么样用opencv将彩色图片转化成像素值只有0和255的灰度图? 进行灰度化,IplImage* pImg = cvLoadImage( "C:\\1.bmp", 0 ); 这样图像已经灰度化,然后调用cvThreshold(image, image, 125, 255, CV_THRESH_BINARY); 就可以了,125那里是你所用的阈值,这就是最简单的二值化,你要用ostu,或者别的高级一点的,就要自己写函数了   // Truncate v