문제

JPG 이미지로 문서를 스캔하고 있습니다. 스캐너는 모든 페이지를 색상으로 또는 모든 페이지를 흑백으로 스캔해야합니다. 많은 페이지가 색상이므로 모든 페이지를 색상으로 스캔해야합니다. 스캔이 완료되면 .NET가있는 이미지를 검사하고 이미지를 검은 색과 흰색의 이미지를 감지하여 해당 이미지를 회색 스케일로 변환하고 저장에 저장할 수 있습니다.

.NET으로 그레이 스케일 이미지를 감지하는 방법을 아는 사람이 있습니까?

알려주세요.

도움이 되었습니까?

해결책

색상을 테스트하는 간단한 알고리즘 : 루프 (너비 및 높이)를 위해 중첩 된 픽셀별로 이미지 픽셀을 걸고 픽셀의 RGB 값이 동일한 지 확인하십시오. 그들이 아닌 경우 이미지에는 색상 정보가 있습니다. 이 조건을 만나지 않고 모든 픽셀을 통해 끝까지 만들면 회색 스케일 이미지가 있습니다.

보다 복잡한 알고리즘을 사용한 개정 :

이 게시물의 첫 번째 Rev에서 나는 각 픽셀의 RGB가 값이 같으면 픽셀이 회색 스케일이라고 가정하는 간단한 알고리즘을 제안했습니다. 따라서 0,0,0 또는 128,128,128 또는 230,230,230의 RGB는 모두 회색으로 테스트되는 반면 123,90,78은 그렇지 않습니다. 단순한.

다음은 회색의 분산을 테스트하는 코드 스 니펫입니다. 두 가지 방법은보다 복잡한 프로세스의 작은 하위 섹션이지만 원래 질문에 도움을 줄 수있는 충분한 원시 코드를 제공해야합니다.

/// <summary>
/// This function accepts a bitmap and then performs a delta
/// comparison on all the pixels to find the highest delta
/// color in the image. This calculation only works for images
/// which have a field of similar color and some grayscale or
/// near-grayscale outlines. The result ought to be that the
/// calculated color is a sample of the "field". From this we
/// can infer which color in the image actualy represents a
/// contiguous field in which we're interested.
/// See the documentation of GetRgbDelta for more information.
/// </summary>
/// <param name="bmp">A bitmap for sampling</param>
/// <returns>The highest delta color</returns>
public static Color CalculateColorKey(Bitmap bmp)
{
    Color keyColor = Color.Empty;
    int highestRgbDelta = 0;

    for (int x = 0; x < bmp.Width; x++)
    {
        for (int y = 0; y < bmp.Height; y++)
        {
            if (GetRgbDelta(bmp.GetPixel(x, y)) <= highestRgbDelta) continue;

            highestRgbDelta = GetRgbDelta(bmp.GetPixel(x, y));
            keyColor = bmp.GetPixel(x, y);
        }
    }

    return keyColor;
}

/// <summary>
/// Utility method that encapsulates the RGB Delta calculation:
/// delta = abs(R-G) + abs(G-B) + abs(B-R) 
/// So, between the color RGB(50,100,50) and RGB(128,128,128)
/// The first would be the higher delta with a value of 100 as compared
/// to the secong color which, being grayscale, would have a delta of 0
/// </summary>
/// <param name="color">The color for which to calculate the delta</param>
/// <returns>An integer in the range 0 to 510 indicating the difference
/// in the RGB values that comprise the color</returns>
private static int GetRgbDelta(Color color)
{
    return
        Math.Abs(color.R - color.G) +
        Math.Abs(color.G - color.B) +
        Math.Abs(color.B - color.R);
}

다른 팁

이를 위해 라이브러리를 찾을 수없는 경우 이미지의 픽셀의 많은 (또는 전부)를 잡고 R, G 및 B 값이 특정 임계 값 (경험적으로 설정 될 수 있는지 확인할 수 있습니다. 서로의 설정으로). 그들이 있다면, 이미지는 회색체입니다.

그래도 테스트의 임계 값을 0보다 조금 더 크게 만들 것입니다 ... 예를 들어 r = g를 테스트하지는 않지만 (ABS (rg) <e)는 e가 당신의 임계 값입니다. 그렇게하면 당신이 당신의 원래 이미지와 스캐닝 기술이주지 않는 한, 당신의 거짓 색상 긍정을 낮추는 것입니다. 정확하게 그레이 스케일.

더 빠른 Versión. 8의 임계 값으로 테스트하십시오.

사용:

bool grayScale;
Bitmap bmp = new Bitmap(strPath + "\\temp.png");
grayScale = TestGrayScale(bmp, 8);
if (grayScale)
   MessageBox.Show("Grayscale image");


/// <summary>Test a image is in grayscale</summary>
/// <param name="bmp">The bmp to test</param>
/// <param name="threshold">The threshold for maximun color difference</param>
/// <returns>True if is grayscale. False if is color image</returns>
public bool TestGrayScale(Bitmap bmp, int threshold)
{
    Color pixelColor = Color.Empty;
    int rgbDelta;

    for (int x = 0; x < bmp.Width; x++)
    {
        for (int y = 0; y < bmp.Height; y++)
        {
            pixelColor = bmp.GetPixel(x, y);
            rgbDelta = Math.Abs(pixelColor.R - pixelColor.G) + Math.Abs(pixelColor.G - pixelColor.B) + Math.Abs(pixelColor.B - pixelColor.R);
            if (rgbDelta > threshold) return false;
        }
    }
    return true;
}

더 빠른 것이 있습니까?

JPEG는 메타 데이터를 지원하므로 먼저 스캐너 소프트웨어가 저장된 이미지에 특수 데이터를 배치하고 해당 정보에 의존 할 수 있는지 확인해야합니다.

그만큼 답변 나는 파이썬 섹션에 게시했습니다 도움이 될 수 있습니다. 웹에서 인간이 회색차가 종종 동일한 r, g, b 값을 가지고 있지 않다는 것을 웹에서 찾을 수 있습니다. 분산 계산과 일종의 샘플링 프로세스를 계산해야하므로 백만 픽셀을 확인할 필요가 없습니다. Paul이 제공 한 솔루션은 최대 차이를 기반으로하므로 스캐너의 단일 레드 픽셀 인공물이 회색차 이미지를 비 그레이 스케일로 바꿀 수 있습니다. 내가 게시 한 솔루션은 13,000 개의 이미지에서 99.1% 정밀도와 92.5% 리콜을 받았습니다.

이 접근법은 코드가 가장 적어야하며 JPEG에서 테스트되었습니다. 아래의 bimage는 바이트 어레이입니다.

 MemoryStream ms = new MemoryStream(bImage);
 System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms);
 if (returnImage.Palette.Flags == 2)
 {
      System.Diagnostics.Debug.WriteLine("Image is greyscale");
 }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top