سؤال

أنا مسح المستندات إلى صور JPG. يجب على الماسح الضوئي مسح جميع الصفحات بلون أو جميع الصفحات بالأبيض والأسود. نظرا لأن العديد من صفحاتي هي اللون، يجب أن أشرح جميع الصفحات بلون. بعد اكتمال المسح، أود فحص الصور باستخدام .NET وحاول اكتشاف الصور باللونين الأبيض والأبيض حتى أتمكن من تحويل هذه الصور إلى تدرج الرمادي وحفظها على التخزين.

هل يعرف أي شخص كيفية اكتشاف صورة رمادية مع .NET؟

أخبرونى من فضلكم.

هل كانت مفيدة؟

المحلول

خوارزمية بسيطة لاختبار اللون: قم بالسير بكسل الصورة بقلم بكسل في متداخلة حلقة (العرض والطول) واختبار لمعرفة ما إذا كانت قيم RGB في بكسل متساوية. إذا لم تكن ثم تحتوي الصورة على معلومات الألوان. إذا قمت بإنجاحها طوال الطريق من خلال جميع البكسل دون مواجهة هذه الحالة، فسيكون لديك صورة على نطاق رمادي.

مراجعة مع خوارزمية أكثر تعقيدا:

في المراجعة الأولى من هذا المنصب اقترحت خوارزمية بسيطة تفترض أن البكسلات هي مقياس رمادي إذا كانت كل RGB في كل بكسل متساوية. حتى RGBS من 0،0،0 أو 128،128،128 أو 230،230،230 من شأنه أن يختبر كل شيء رمادي بينما 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 B ضمن عتبة معينة (التي قد تقوم بتعيينها تجريبيا ، أو لديك كإعداد) من بعضها البعض. إذا كانت، فإن الصورة رمادية.

بالتأكيد سأجعل العتبة للاختبار أكبر قليلا من 0، على الرغم من ... لذلك لن أقوم باختبار R = G، على سبيل المثال، ولكن (ABS (RG) <E) حيث 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. تحتاج إلى بعض حساب التباين ونوع من عملية أخذ العينات حتى لا تضطر إلى التحقق من مليون بكسل. يستند Solution Paul Paul إلى الفرق الأقصى لذا فإن قطعة أثرية حمراء حمراء من الماسح الضوئي يمكن أن تتحول صورة رمادية إلى الرمادي. الحل الذي نشرته حصلت على 99.1٪ الدقة و 92.5٪ أذكر على 13000 صورة.

أعتقد أن هذا النهج يجب أن يتطلب أقل رمز، لقد تم اختباره على JPEGS. 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