Pull to refresh

Comments 16

А как будет работать скрипт с ограниченным набором изображений, скажем, 100 или около того?
Сильно будет зависить от того, какие картинки составляют датасет и какую картинку мы ими апроксимируем. Если повезет, может получится нормально, а не повезет — будет некрасиво. Ну и будет много повторений одних и тех же изображений в итоге, а это некрасиво смотрится
Но можно поэксперементировать :)
Ну и будет много повторений одних и тех же изображений в итоге, а это некрасиво смотрится

Но в приведённых в статье примерах и сейчас много повторений. Может быть для разнообразия хотя бы вращать исходные паттерны?
Вы правы, можно попробовать, должно стать лучше
Здесь n — количество признаков, в нашем случае 3 x n x m

Я так понимаю, здесь ошибка, и вместр первой n следует использовать другой символ, например, N?

А вам спасибо за интересную статью!

Спасибо за статью. Прекрасный баланс между математикой, кодом, и объяснением что к чему

Без нейронок не модно же такие задачи решать.

Еще немного про функцию потерь. У вас формулы расстояния между цветами:


  1. лучше не использовать. По производительности нет выигрыша, и сильно ошибается
  2. корень можно не считать, так как он не влияет на результат сравнения. Получится просто d = (R1-R2)² + (G1-G2)² + (B1-B2)²
  3. добавились коэффициенты, но эти коэффициенты показывают лишь вклад в яркость — их нельзя здесь применять. Так например синяя компонента даёт самый малый вклад в яркость, но самый большой — в насыщенность
  4. возведение коэффициентов в квадрат, это просто плохо

https://en.wikipedia.org/wiki/Color_difference

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


Заголовок спойлера

Рандомная картинка из интернета

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

Да, видимо, вы правы. Если использовать MSE двух тензоров как функцию потерь, то должно получится что-то подобное. Но я не пробовал ввиду того, что такая программа очень долго будет выполнятся (быть может, есть более эффективный способ) :)

Можно сначала отсеять большинство изображений вашим способом.

Писал когда-то такое на C#. Девушек развлекать, составляя их мозаики из их же картинок.

Подход очень похож на ваш был. С одним небольшим улучшением.

Допустим, мы уже нашли маленькую картинку, наилучшим образом подходящую на роль «пиксела». Но ведь почти наверняка её RGB не на 100% соответствует желаемому. Что делать? Тогда мы берём и чуть-чуть «докрашиваем» её на недостающую разницу по R, G, и B, чтобы она совпала точно. Итоговая мозаика получается куда глаже и достовернее.
Написал 2001 скринсайэвер на C++ и DirectX — бесконечно мозайка увеличивается, и там проявляются другие картинки, кторые тоже мозайки, и так до бесконечности, назывался Mosaic Screen Saver.
Ух, исходники даже нашел :) Тольно на 10ке хрен знает как его включить

Спасибо за статью!
Пошел немного по другому: датасет пообрезал и пережал в картинки 16х16, потом для каждой рассчитано среднее по hue-каналу, запомнено напротив имени файла и сортировано по средним. Целевое изображение разбивается на плитку соответственно 16х16 и для каждого фрагмента также считается среднее, находится по базе номер, который этот фрагмент бы в ней занял, и поднимаем в окрестности этого номера кучку картинок, которые уже можно сравнивать суммами квадратов разностей. Ну и наиболе подходящие пазлы идут в конечную картинку


Предобработка
using Images
using Statistics: mean

pth = s"D:\inter3\Cat Annotation Dataset"
folderz = readdir(pth)

@time for foldr in folderz

    filez = readdir("$pth/$foldr")

    for fl in filez

        imgi = load("$pth/$foldr/$fl")
        if min( size(imgi)... ) < 256 continue end
        if typeof(tmp[1]) == Gray{Normed{UInt8,8}} continue end

        if min( size(imgi)... ) < 512
            imgc = imgi[1:256, 1:256]
        else
            imgc = imgi[1:512, 1:512]
        end
        imgr = imresize(imgc, sz, sz)
        save("ketz16/$fl", imgr)
    end
end

filez = readdir("ketz16")
meanz = zeros(length(filez))

for (i,fl) in enumerate(filez)
    tmp = load("ketz16/$fl")
    meanz[i,:] = mean( hue.( float.( HSV.(tmp) ) ) )
end

indcs = sortslices( [meanz filez], dims = 1 );

using DelimitedFiles
# indcs = readdlm("meanzandnamez.txt", ',', Float64)
open("meanzandnamezcat.txt", "w") do io
           writedlm(io, indcs)
       end

замощение картинки
imgo = load("test3.jpg")
n, m = size(imgo)
n ÷= sz
m ÷= sz

Mx = [ imgo[(i-1)*sz:i*sz-1, (j-1)*sz:j*sz-1] for i in 2:n, j in 2:m ];
function simil(part, w)

    u = mean( hue.( float.( HSV.(part) ) ) )
    ii = searchsorted(indcs[:,1], u)
    ii.start+w >= size(indcs,1) ? (ww = size(indcs,1)-ii.start-1) : (ww = w)
    dists = []

    for i in ii.stop-w:ii.start+ww

        tmp = load("ketz16/$(indcs[i,2])")
        if typeof(tmp[1]) == Gray{Normed{UInt8,8}} continue end
        s = sum(x-> x^2, Float64.(channelview(part)) - Float64.(channelview(tmp)) )
        push!( dists,  s)
    end

    num = ii.stop-w + argmin(dists) - 1
    load("ketz16/$(indcs[num,2])")
end

@time Mxx = [ simil(prt, 80) for prt in Mx ];

function combiner(arr)
    N, M = size(arr)
    n, m = size(arr[1])
    brr = zeros(RGBA{Normed{UInt8,8}}, N*n, M*m)

    for i in 1:N, j in 1:M
        x = 1+n*(i-1)
        y = 1+m*(j-1)
        brr[x:x+n-1,y:y+m-1] = arr[i,j]
    end
    brr
end

save( "testt3.jpg", combiner(Mxx) )

image

Теперь нужен датасет поприличней

Sign up to leave a comment.

Articles