I have run into a strange issue. I am using G'MIC for a massively parallel image processor. On one 4-core machine, I have a process shelling out to G'MIC to perform some inpainting. There are four copies of this process running. 99% of the time, this works fine. However, over the course of processing many images over many hours, I will sometimes get an incorrect output based on the input. The cause seems to be from reading from another image, but when I look at the command G'MIC is running, it is pointing at the correct image and the image itself is correct!
This is difficult to explain, so I have created an example script that causes this to happen very quickly. I have tested on G'MIC 1.5.8.3 and 1.5.8.2. What I am doing here is creating 99 images, and then having 50 G'MIC processes spin up and inpaint the images, saving output in individual directories based on an integer I feed ARGV. I don't know if this issue arises on other functions, but I would be glad to test. Of course, I'm not going to be running 50 G'MIC processes on a 4-core machine, but this just forces the bug to happen in a single quick run (hopefully) rather than over the course of many hours.
I'm sorry I used ImageMagick to create the images! I'd like to know how to do so with G'MIC but I had trouble with the syntax
Simply save these files on a machine with Ruby, G'MIC, ImageMagick, and Ghostscript. Then run:
I'd be happy to answer any questions.
Thanks!
Oh, I should note an easy way to find troublesome images is to go to the output directory and run:
ls -la * | awk '{print$5, $9}' | sort | uniq -c
This will group images by name and file size so you can identify the bad seeds from there. I got 12 'bad' images in my run.
# debug.rb (run me!)
# create an inpaint mask
`convert -background transparent -fill black -pointsize 72 -size 165x70 -gravity center label:+++++++++ i.gif`
`convert i.gif -alpha extract -alpha on i.gif`
# create a bunch of images where the filename is a number and the image is the number
(1..99).each do |n|
`convert -background lightblue -fill blue -pointsize 72 -size 165x70 -gravity center label:#{n} i#{n}.gif`
end
# make a directory for output
Dir.mkdir("output")
# run 50 inpaint processes and feed it the process number
`seq 1 50 | xargs -P 50 -I {} ruby inpaint.rb {}`
# inpaint.rb
# create an array 1-99
images = *(1..99)
randomize the array
images.shuffle!
# make a directory for each argument (the process "id")
dir = Dir.mkdir("#{Dir.pwd}/output/#{ARGV[0]}")
# iterate through the array, inpainting the image with that number... ouput to output/process/inpaint-[#].png
images.each do |n|
`gmic i#{n}.gif i.gif --inpaint[-2] [-1] -remove[0] -remove[0] -output output/#{ARGV[0]}/inpaint-#{n}.png`
end