Удаление артефактов JPEG в C#

Свойства являются просто удобным способом записать get_MyValue() и set_MyValue(value) присвоение разрешения, а не нормальный вызов метода (использующий круглую скобку).

то, К чему Вы получаете доступ, является на самом деле свойством.NET, C# имеет свой собственный синтаксис для доступа к ним. С тех пор под кожей реальное get_ и set_ методы создаются, таким образом, Вы могли просто показать те методы (чтобы сделать Ваше независимое от языка UML - например, сделать Ваше одинаково применимое UML к разработчику VB.NET)

... или как Вы предположили, представьте свой собственный стереотип!

5
задан Community 8 February 2017 в 14:14
поделиться

8 ответов

Что ж, я попробовал кое-что, что далеко от совершенства, но полагаю, что это может быть полезно кому-то другому.

Я получил:

alt text

Возникшие проблемы: тени далеки достаточно от «не совсем белого», чтобы их было трудно преобразовать автоматически, и даже если бы вы это сделали, тень все равно будет в самом изображении. Блики сверху ... втулки тоже ближе к белому, чем части со сглаживанием. На изображении есть от трех до семи белых пятен, не связанных ни с одним из основных углов; и, наконец, по краям все еще осталось немного белого (возможно, можно было бы избавиться от него, настроив код, но не сняв часть бликов сверху.

Неэффективный код C #:

    static void Main()
    {
        Bitmap bmp=new Bitmap("test.jpg");

        int width = bmp.Width;
        int height = bmp.Height;
        Dictionary<Point, int> currentLayer = new Dictionary<Point, int>();
        currentLayer[new Point(0, 0)] = 0;
        currentLayer[new Point(width - 1, height - 1)] = 0;
        while (currentLayer.Count != 0)
        {
            foreach (Point p in currentLayer.Keys)
                bmp.SetPixel(p.X, p.Y, Color.Black);
            Dictionary<Point, int> newLayer = new Dictionary<Point, int>();
            foreach (Point p in currentLayer.Keys)
                foreach (Point p1 in Neighbors(p, width, height))
                    if (Distance(bmp.GetPixel(p1.X, p1.Y), Color.White) < 40)
                        newLayer[p1] = 0;
            currentLayer = newLayer;
        }

        bmp.Save("test2.jpg");
    }

    static int Distance(Color c1, Color c2)
    {
        int dr = Math.Abs(c1.R - c2.R);
        int dg = Math.Abs(c1.G - c2.G);
        int db = Math.Abs(c1.B - c2.B);
        return Math.Max(Math.Max(dr, dg), db);
    }

    static List<Point> Neighbors(Point p, int maxX, int maxY)
    {
        List<Point> points=new List<Point>();
        if (p.X + 1 < maxX) points.Add(new Point(p.X + 1, p.Y));
        if (p.X - 1 >= 0) points.Add(new Point(p.X - 1, p.Y));
        if (p.Y + 1 < maxY) points.Add(new Point(p.X, p.Y + 1));
        if (p.Y - 1 >= 0) points.Add(new Point(p.X, p.Y - 1));
        return points;
    }

Код работает, начиная с две точки; установив их в черный цвет, а затем проверять, не близки ли к белому какие-либо соседи рядом с ними; если они есть, они добавляются в список, который затем выполняется. В конце концов, у него заканчиваются белые пиксели, которые нужно изменить.

В качестве альтернативы вы можете подумать о переделке сайта, чтобы использовать белый фон.

5
ответ дан 14 December 2019 в 04:44
поделиться

Вам придется обрабатывать оттенки не совсем белого цвета как хорошо. Вероятно, когда они изначально сделали iamges и установили цвет фона, было некоторое сглаживание, а затем при сохранении в формате jpg не все цвета будут сохранены идеально. Поэтому, если вы делаете определенный цвет прозрачным, он s не сможет получить все оттенки этого цвета, что оставит много артефактов. Вам нужно что-то, что сделает прозрачность пропорциональной тому, насколько цвет близок к вашему ключевому цвету. Возможно, это проще сделать в виде пакетного сценария в чем-то вроде Photoshop, но я не знаю, нужно ли это делать в реальном времени.

0
ответ дан 14 December 2019 в 04:44
поделиться

Вы не сможете сделать это автоматически со 100% точностью.

Причина в том, что единственная информация, которая у вас есть, - это цвет, который вы знаете, что некоторые пикселя в изображении пытаются хорошо слиться с ним. Только некоторые пиксели изображения будут фактически использовать цвета, равные или близкие к этому значению, для затенения фона, другие будут использовать (в случае белого), потому что фактический представленный объект на самом деле белый (черт возьми, точность эти имперские штурмовики).

Вид сложного машинного обучения для определения того, что представляет собой интересную проблемную область, и может быть интересным проектом для вас, но определенно не поможет быстро решить вашу непосредственную проблему.

Другая ваша проблема заключается в том, даже если вы можете с хорошей надежностью обнаружить те области изображения, которые пытаются слиться с фоном, у вас будут проблемы с их «несмешиванием» и последующим повторным смешиванием их в ваш новый цвет фона, если цвета не будут достаточно совместимыми. В этом случае серый цвет может работать, так как это цвет широкого спектра, такой как белый.

Техника, которую вы хотите использовать, выглядит следующим образом:

  • Используйте алгоритм заливки для выбора, от краев изображения внутрь всех пикселей в пределах x% (1) известного цвета фона.
  • Для этих пикселей устанавливают для их альфа-канала значение, пропорциональное их совпадению с исходным цветом, и устраняют связанный с ним цветовой оттенок. их, а затем повторно смешивая их в ваш новый цвет фона, если цвета не являются разумно совместимыми. В этом случае серый цвет может работать, так как это цвет широкого спектра, такой как белый.

    Техника, которую вы хотите использовать, выглядит следующим образом:

    • Используйте алгоритм заливки для выбора, от краев изображения внутрь всех пикселей в пределах x% (1) известного цвета фона.
    • Для этих пикселей устанавливают для их альфа-канала значение, пропорциональное их совпадению с исходным цветом, и устраняют связанный с ним цветовой оттенок. их, а затем повторно смешивая их в ваш новый цвет фона, если цвета не являются разумно совместимыми. В этом случае серый цвет может работать, так как это цвет широкого спектра, такой как белый.

      Техника, которую вы хотите использовать, выглядит следующим образом:

      • Используйте алгоритм заливки для выбора, от краев изображения внутрь всех пикселей в пределах x% (1) известного цвета фона.
      • Для этих пикселей устанавливают для их альфа-канала значение, пропорциональное их совпадению с исходным цветом, и устраняют связанный с ним цветовой оттенок. от краев изображения внутрь все пиксели в пределах x% (1) известного цвета фона.
      • Для этих пикселей устанавливают для их альфа-канала значение, пропорциональное их совпадению с исходным цветом, и устраняют связанный с ним цветовой оттенок. от краев изображения внутрь все пиксели в пределах x% (1) известного цвета фона.
      • Для этих пикселей устанавливают для их альфа-канала значение, пропорциональное их совпадению с исходным цветом, и устраняют связанный с ним цветовой оттенок.
        • Итак, если фон имеет значение RGB a, b, c, а пиксель имеет значение a + 5, b, c-7, то результат RGBA 5,0,0, ((a + b + c-7) / (a ​​+ b + c) * 256) (1)
      • наложите это альфа-смешанное изображение на квадрат цвета новой фоновой окраски.
      • отображает результат без альфа-канала как новое изображение.

      Это все еще будет иметь проблемы для объектов, цвет которых близок к любому цвету фона. * в случае оригинала может быть, что затенение используется для обозначения присутствия объекта, поэтому заливка заливкой будет «вторгаться» внутрь изображения. * в последнем случае результирующее изображение потеряет четкость объекта, и не будут присутствовать тонкие тени, блики или простые линии, указывающие, где заканчивается объект и заканчивается задний фон.

      Это очень грубый первый вариант. приблизительно, но может покрывать разумный процент от вашей цели. Эти изображения с прозрачными полностью закрытыми отверстиями (например, промежутки во внешней арке в вашем примере) вряд ли когда-либо будут нормально работать в автоматическом режиме, поскольку алгоритм не сможет отличить белые дыры от белого штурмовика.
      Возможно, вы захотите заставить свой алгоритм выделять области изображения, которые он планирует повторно объединить, и разрешить простой выбор регионов для включения / исключения (используя инструмент выбора волшебной палочки из Pain.Net в качестве примера того, как это сделать, если вы хотите быть навороченным, позволяя простой выбор на пиксель с меньшими затратами.


      1. значение x будет тем, что вы настраиваете - возможно, это зависит от некоторых аспектов изображения (скажем, пропорции изображения, близкой к цвет фона), вы можете настроить его автоматически.
      2. Обратите внимание, что в этой формуле предполагается, что цвет близок к белому, для близкого к черному цвету нужно инвертировать
1
ответ дан 14 December 2019 в 04:44
поделиться

Не существует (удаленно простого) способа решить эту проблему программно. Белые области с артефактами y по краю изображения являются результатом пикселей, которые почти белые, но не совсем, поэтому они не воспринимают эффект прозрачности. На маске / кружке кофе также есть пара пятен, которые являются чисто белыми, поэтому они становятся прозрачными и, следовательно, серыми.

Лучше всего связаться с веб-мастером исходного сайта и посмотреть, могут ли они отправить вам исходные изображения, Надеюсь, в фотошопе или другом формате, где исходные слои сохраняются отдельно. Затем вы можете повторно сгенерировать изображения в формате, который сохраняет исходную прозрачность (PNG или что-то в этом роде) или использует ваш градиент для фона (было бы очень сложно сделать это правильно, так как вы не

0
ответ дан 14 December 2019 в 04:44
поделиться

Прокрутите каждый пиксель изображения, если R, G и B больше, чем, скажем, 230, тогда замените цвет желаемым цветом (или прозрачным). Возможно даже утяжелить новый цвет в зависимости от того, насколько далек от «истинного» белого старый цвет.

Ожидайте возникновения проблем, если фактическое изображение также будет белым, иначе вы получите серый штурмовик :)

1
ответ дан 14 December 2019 в 04:44
поделиться

Еще один подход, основанный на диалоге комментариев:

static void Main()
{
    Bitmap mask = new Bitmap(@"mask.bmp");
    Bitmap bmp=new Bitmap(@"test.jpg");
    int width = bmp.Width;
    int height = bmp.Height;

    for(int x=0; x<width; x++)
        for (int y = 0; y < height; y++)
            if (mask.GetPixel(x, y).R < 250)
                bmp.SetPixel(x,y,mask.GetPixel(x,y));
    bmp.Save(@"test3.jpg");
}

Заданная маска:

alt text

Вы получаете результат:

alt text

С границей маски, слегка очищенной в Paint.NET с помощью анти алиасинг отключен. Опять же, это применимо только в том случае, если вы можете различить, какая граница используется ... но все получилось хорошо ... кроме зеленого ...

1
ответ дан 14 December 2019 в 04:44
поделиться

Спасибо всем за ответы .. все хорошие предложения ..

Вот что я вчера придумал:

public const int PIXEL_REGION = 60;
public const int TRANSPARENT_DISTANCE = 60;
public static readonly Color TRANSPARENT_COLOR = Color.White;

private System.Drawing.Image ProcessImage(System.Drawing.Image image)
{
    Bitmap result = new Bitmap(image.Width, image.Height);

    Bitmap workImage = new Bitmap(image);

    for (int x = 0; x < image.Width; x++)
    {
        for (int y = 0; y < image.Height; y++)
        {
            Color color = workImage.GetPixel(x, y);

            if (x < PIXEL_REGION || x > image.Width - PIXEL_REGION || y < PIXEL_REGION || y > image.Height - PIXEL_REGION)
            {
                double distance = CalculateColourDistance(TRANSPARENT_COLOR, color);

                if(distance < TRANSPARENT_DISTANCE)
                {
                    result.SetPixel(x, y, Color.Transparent);
                    continue;
                }
            }

            result.SetPixel(x, y, color);
        }
    }

    return result;
}

private double CalculateColourDistance(Color c1, Color c2)
{
    int a = c2.A - c1.A;
    int r = c2.R - c1.R;
    int g = c2.G - c1.G;
    int b = c2.B - c1.B;

    return Math.Sqrt(Math.Pow(a, 2) + Math.Pow(r, 2) + Math.Pow(g, 2) + Math.Pow(b, 2));
}

Это не самый красивый код в книге, но то, что он делает, касается каждого пикселя в пиксельная область вычисляет расстояние между Color.White и моим собственным цветом, и когда оно меньше заданного расстояния, оно будет окрашено прозрачным.

Этот фрагмент кода дает следующий результат:

TB-5404 transformed v 2.0

Неплохо вы .. но это все равно отстой :)

У меня есть один трюк в рукаве, которым я тоже поделюсь с вами, если он удастся ...

0
ответ дан 14 December 2019 в 04:44
поделиться

Здесь это еще одна неудачная попытка;)

У меня возникла идея ... в фильмах используется зеленый экран, почему бы не использовать зеленый оверлей для моего изображения .. Итак, вот наложение:

Green overlay with transparent inner thing

И результаты:

Green stuff all over the place

Итак, я получил еще один ценный урок о сжатии PNG .. Я также пробовал это с bmp, но почему-то у меня всегда получается зеленая рамка .. Я могу попробовать стереть это, но, может быть, мне просто стоит оставить его на белом фоне, обвести какую-нибудь дурацкую рамку вокруг и покончить с этим ...

Ну что ж ...;)

0
ответ дан 14 December 2019 в 04:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: