25

我正在尝试编写一个转换器算法,该算法采用 JPEG 图像并返回其 PGM(便携式灰度图)版本。问题是我无法理解“官方”JPG->PGM 转换器如何从经典 RGB 格式开始分配给最终像素(我猜是 0->255)的值。

一开始,我使用了这个公式(与OpenCV的CV_RGB2GRAY转换使用的相同):

0.30*R + 0.59*G + 0.11*B = 值

我编写了一个简单的代码来测试我的结果:它采用彩色图像及其 PGM 版本(已经使用 GIMP 转换)。然后它使用前面的公式转换彩色图像。目标是获得一个像素到像素等于 PGM 输入的灰度图像。

此时,它不会返回相同的值。你能帮助我吗?

4

6 回答 6

32

问题是我无法理解“官方”JPG->PGM 转换器如何从经典 RGB 格式开始分配给最终像素(我猜是 0->255)的值。

这些“官方”工具正在使用的转换中可能存在伽玛调整。
也就是说,它不仅仅是一个线性变换。

有关详细信息,请参阅此 Wikipedia 部分:将颜色转换为灰度

我相信您想使用. 尝试一下,看看它是否与您期望的结果相符。Csrgb

基本上,你会这样做:

  1. R, G, B颜色(每个在[0,1]范围内)
    • 如果它们在范围内0..255,只需除以255.0
  2. 计算Clinear = 0.2126 R + 0.7152 G + 0.0722 B
    • 这可能是您之前应用的线性变换
  3. 根据它的公式计算,基于CsrgbClinear
    • 这是您缺少的非线性伽马校正部分
    • 看看这个 WolframAlpha 图
    • Csrgb = 12.92 Clinear什么时候Clinear <= 0.0031308
    • Csrgb = 1.055 Clinear1/2.4 - 0.055什么时候Clinear > 0.0031308
于 2013-07-12T16:22:40.393 回答
4

哈罗德关于“Y 平面”的观点:标准彩色 JPEG 使用YCbCr颜色空间进行编码,其中 Y 是亮度分量(即亮度),Cb 和 Cr 是蓝差和红差色度分量。因此,将彩色 JPEG 转换为灰度的一种方法是简单地删除 Cb 和 Cr 分量。

有一个名为jpegtranthan 的实用程序可以使用该-grayscale选项无损地执行此操作。(无损部分只有在你想以 JPEG 而不是 PGM 结束时才有意义,以避免生成损失。)无论如何,这可能是进行这种转换的最快方法,因为它甚至不解码将图像转换为像素,更不用说对每个像素进行数学运算了。

于 2017-12-15T21:16:26.423 回答
1

理论上,只需几个像素(在本例中为 3 个),您就可以确定他们的算法在做什么。只要选择你的三个像素(p1、p2、p3)、它们的 RGB 值和它们的 PGM 灰度值,你就有:

RedConstant * p1.redValue + GreenConstant * p1.greenValue + BlueConstant * p1.blueValue = p1.grayValue

RedConstant * p2.redValue + GreenConstant * p2.greenValue + BlueConstant * p2.blueValue = p2.grayValue

RedConstant * p3.redValue + GreenConstant * p3.greenValue + BlueConstant * p3.blueValue = p3.grayValue。

然后解决这个问题(查找“方程求解器”或其他东西),看看他们使用的常数是什么。

于 2013-07-12T13:51:51.010 回答
0

在 OPENCV PYTHON 中将 RGB 图像转换为灰度的简单算法!

我使用了注释,所以代码是不言自明的。但它运行迅速。

import cv2
import numpy as np
img1 = cv2.imread('opencvlogo.png')
row,col,ch = img1.shape
g = [ ]  #the list in which we will stuff single grayscale pixel value inplace of 3 RBG values
#this function converts each RGB pixel value into single Grayscale pixel value and appends that value to list 'g'
def rgb2gray(Img):
    global g
    row,col,CHANNEL = Img.shape
    for i in range(row) :
        for j in range(col):
        a =      (   Img[i,j,0]*0.07  +  Img[i,j,1]*0.72 +    Img[i,j,2] *0.21   ) #the algorithm i used id , G =  B*0.07 + G*0.72 + R* 0.21
                                                                                   #I found it online
        g.append(a)
rgb2gray(img1)  #convert the img1 into grayscale
gr = np.array(g)  #convert the list 'g' containing grayscale pixel values into numpy array
cv2.imwrite("test1.png" , gr.reshape(row,col)) #save the image file as test1.jpg

所以我使用了这个图像文件......在此处输入图像描述

我的程序生成以下灰度文件..

在此处输入图像描述

于 2017-05-20T17:05:25.973 回答
-1

将默认 RGB ColorModel 中的单个输入像素转换为单个灰色像素。

/* Convertation function 
 * @param x    the horizontal pixel coordinate
 * @param y    the vertical pixel coordinate
 * @param rgb  the integer pixel representation in the default RGB color model
 * @return a gray pixel in the default RGB color model.*/

    public int filterRGB(int x, int y, int rgb) {
    // Find the average of red, green, and blue.
    float avg = (((rgb >> 16) & 0xff) / 255f +
                 ((rgb >>  8) & 0xff) / 255f +
                  (rgb        & 0xff) / 255f) / 3;
    // Pull out the alpha channel.
    float alpha = (((rgb >> 24) & 0xff) / 255f);

    // Calculate the average.
    // Formula: Math.min(1.0f, (1f - avg) / (100.0f / 35.0f) + avg);
    // The following formula uses less operations and hence is faster.
    avg = Math.min(1.0f, 0.35f + 0.65f * avg);
    // Convert back into RGB.
   return (int) (alpha * 255f) << 24 |
          (int) (avg   * 255f) << 16 |
          (int) (avg   * 255f) << 8  |
          (int) (avg   * 255f);
}
于 2019-01-02T14:34:47.353 回答
-4

平均法是最简单的一种。你只需要取三种颜色的平均值。由于它是 RGB 图像,因此这意味着您将 r 与 g 与 b 相加,然后将其除以 3 以获得所需的灰度图像。

它以这种方式完成。

Grayscale = (R + G + B / 3)

如果您有如上图所示的彩色图像,并且您想使用平均方法将其转换为灰度。

于 2019-02-02T17:50:36.420 回答