2017-01-07 18 views
0

Редактировать 1: Переписанный вопрос, так что понятнее.Черно-белый (не серый) фильтр в svg, в идеале snap.svg

Это действительно раскололось.

Я хотел бы применить фильтр к изображению, чтобы значения над определенным порогом отображались как полностью белые, а все значения, которые равны или меньше порога, полностью черные.

здесь карта, представляющая значения RGB из 3х3 пикселей изображения:

|(255,255,255)|(220,220,220)|(100,100,100)| 
|(254,254,254)|(12 ,12 ,12)|(38 ,38 ,38)| 
|(201,201,201)|(105,105,105)|(60 ,60 ,60)| 

После применения моего фильтра я хотел бы получить изображение, где все значения больше, чем 200, преобразуются в (255,255,255) и все значения равны или менее 200, преобразуются в (0,0,0), такие как:

|(255,255,255)|(255,255,255)|(0 ,0 ,0 )| 
|(255,255,255)|(0 ,0 ,0 )|(0 ,0 ,0 )| 
|(255,255,255)|(0 ,0 ,0 )|(0 ,0 ,0 )| 

Любые идеи о том, где я должен начать? Это возможно даже в svg? Я знаю, что могу создавать матричные умножения в фильтрах в svg, но я не знаю, как подойти к этой проблеме.

спасибо!

Edit 1: Связанные вопрос я отвечал в математике обмена: https://math.stackexchange.com/questions/2087482/creating-binary-matrix-for-threshold-as-a-result-of-matrix-multiplcation

Edit 2:: Выдержки из кода Snap.svg: эта матрица преобразует цветное изображение в оттенках серого:

<feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0"/> 

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

Дополнительная информация: Согласно MSDN, это то, как происходит умножение:

Resulting vector my coveted matrix  original vector 
    | R' |  | a00 a01 a02 a03 a04 | | R | 
    | G' |  | a10 a11 a12 a13 a14 | | G | 
    | B' | = | a20 a21 a22 a23 a24 | * | B | 
    | A' |  | a30 a31 a32 a33 a34 | | A | 
    | 1 |  | 0 0 0 0 1 | | 1 | 

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

+0

Вы можете посмотреть на фильтры SVG. Трудно видеть, что вам нужно. Есть ли исходное изображение или svg, которые будут вытерты, или что? – Ian

+0

Никаких конкретных svg или изображений. В основном мне нужно (чтобы создать) фильтр, который принимает изображение и вместо него возвращает монохроматическое изображение (не в оттенках серого, а в черном и белом). Все значения больше, чем x, как белые, а все значения, малые или равные x, отображаются как черные. –

+0

Если вы знаете о встроенном svg-фильтре или таком, это было бы здорово. Если нет, мне придется понять эту проблему. http://math.stackexchange.com/questions/2087482/creating-binary-matrix-for-threshold-as-a-result-of-matrix-multiplcation –

ответ

2

Вы можете достичь порогового значения с помощью примитива фильтра <feComponentTransfer type="discrete">.

Вот пример.

<svg width="300" height="550" style="background-color: linen"> 
 
    <defs> 
 
    <linearGradient id="gradient"> 
 
     <stop offset="0" stop-color="white"/> 
 
     <stop offset="1" stop-color="black"/> 
 
    </linearGradient> 
 
    
 
    <filter id="threshold" color-interpolation-filters="sRGB"> 
 
     <feComponentTransfer> 
 
     <feFuncR type="discrete" tableValues="0 1"/> 
 
     <feFuncG type="discrete" tableValues="0 1"/> 
 
     <feFuncB type="discrete" tableValues="0 1"/> 
 
     </feComponentTransfer> 
 
    </filter> 
 
    </defs> 
 

 
    <rect x="50" y="50" width="200" height="200" fill="url(#gradient)"/> 
 
    <rect x="50" y="300" width="200" height="200" fill="url(#gradient)" filter="url(#threshold)"/> 
 
</svg>

Как это примитивные работы является то, что вы создаете таблицу полос для каждого компонента цвета. Однако количество полос связано со входом, а не с выходом. Подумайте об этом, поскольку ввод разделен на несколько диапазонов равного размера. Затем вы назначаете выходное значение для каждого диапазона. Поэтому, если вы хотите, чтобы раскол произошел на 50% (R, G или B = 0,5 (128)), вы создаете две полосы «0 1». Значениям в первом диапазоне (0 -> 0,5) присваивается значение 0, а значениям во втором диапазоне (0,5 -> 1) присваивается значение 1.

Так, например, если вы хотите установить порог на 20 % (0,2 или 51), вам нужно создать пять полос. И значения выходной таблицы будут «0 1 1 1 1».

<svg width="300" height="550" style="background-color: linen"> 
 
    <defs> 
 
    <linearGradient id="gradient"> 
 
     <stop offset="0" stop-color="white"/> 
 
     <stop offset="1" stop-color="black"/> 
 
    </linearGradient> 
 
    
 
    <filter id="threshold" color-interpolation-filters="sRGB"> 
 
     <feComponentTransfer> 
 
     <feFuncR type="discrete" tableValues="0 1 1 1 1"/> 
 
     <feFuncG type="discrete" tableValues="0 1 1 1 1"/> 
 
     <feFuncB type="discrete" tableValues="0 1 1 1 1"/> 
 
     </feComponentTransfer> 
 
    </filter> 
 
    </defs> 
 

 
    <rect x="50" y="50" width="200" height="200" fill="url(#gradient)"/> 
 
    <rect x="50" y="300" width="200" height="200" fill="url(#gradient)" filter="url(#threshold)"/> 
 
</svg>

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

Чтобы продемонстрировать это, в этом последнем примере я использую некоторый javascript для обновления таблицы фильтров на основе значения, заданного ползунком диапазона.

var selector = document.getElementById("selector"); 
 
var funcR = document.getElementById("funcR"); 
 
var funcG = document.getElementById("funcG"); 
 
var funcB = document.getElementById("funcB"); 
 

 
function updateFilter() { 
 
    // Input value 
 
    var threshold = selector.value; 
 
    // Create the table 
 
    var table = "0 ".repeat(threshold) + "1 ".repeat(256-threshold); 
 
    // Update the filter components 
 
    funcR.setAttribute("tableValues", table); 
 
    funcG.setAttribute("tableValues", table); 
 
    funcB.setAttribute("tableValues", table); 
 
} 
 

 
selector.addEventListener('input', updateFilter); 
 

 
// Call the filter updater once at the start to initialise the filter table 
 
updateFilter();
<svg width="300" height="300" style="background-color: linen"> 
 
    <defs> 
 
    <filter id="threshold" color-interpolation-filters="sRGB"> 
 
     <feComponentTransfer> 
 
     <feFuncR id="funcR" type="discrete" tableValues="0 1 1 1"/> 
 
     <feFuncG id="funcG" type="discrete" tableValues="0 1 1 1"/> 
 
     <feFuncB id="funcB" type="discrete" tableValues="0 1 1 1"/> 
 
     </feComponentTransfer> 
 
    </filter> 
 
    </defs> 
 

 
    <image xlink:href="https://placekitten.com/g/300/300" 
 
     x="50" y="50"width="200" height="200" 
 
     filter="url(#threshold)"/> 
 
</svg> 
 

 
<form> 
 
    <input id="selector" type="range" min="0" max="256"/> 
 
</form>

+0

IE/Edge поддерживает только до 64 значений в массиве feComponentTransfer - только хэдшоп –

+0

Это, похоже, не так. Я немного изменил скрипт, чтобы он запускался в IE, и, похоже, он отлично работает в IE11. Не попробовал Edge. https://jsfiddle.net/ga0xh0oj/ –

+0

Используется для случая. Приятно, если это исправлено. –

0

Преобразование RGB в оттенки серого, на которое вы ссылаетесь, является линейным процессом. Это можно сделать с помощью матричного умножения. Каждое выходное значение представляет собой взвешенную сумму значений R, G и B. Если вы выберете один и тот же вес для каждого выходного канала, получившееся изображение RGB станет серым.

Бинаризация - нелинейная операция. Поэтому невозможно изменить эту матрицу преобразования, чтобы она делала черно-белые вместо оттенков серого.

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

+0

, как я люблю раскомментированные downvotes ... – Piglet

2

Это то, к чему используется примитив feComponentTransfer для SVG, с типом = "дискретный". Пожалуйста, обратитесь к webplatform documentation, чтобы понять, как использовать этот элемент.

 Смежные вопросы

  • Нет связанных вопросов^_^