Why are these scripted gimp image modifications not being persisted? - gimp

This is my first foray into gimp scripting, and I seem to be having some basic misunderstanding. I've written the following code which is intended to convert white into transparency in the specified file, and to export the result as a png file:
(define (edit-name original-name)
(let* ((pos (- (string-length original-name) 4))
(suffix (substring original-name pos))
(prefix (substring original-name 0 pos))
(new-name (string-append prefix ".png")))
new-name))
(define (my-process filename)
(let* ((color '(0 0 0))
(image (car (gimp-file-load RUN-NONINTERACTIVE filename filename)))
(drawable (car (gimp-image-get-active-layer image)))
(filename-modified (edit-name filename)))
(if (not (gimp-drawable-is-rgb drawable))
(gimp-image-convert-rgb image))
(plug-in-colortoalpha RUN-NONINTERACTIVE image drawable color)
(file-png-save2 RUN-NONINTERACTIVE image drawable filename-modified filename-modified 0 9 1 1 1 1 1 0 1)))
This script is saved in the file ~/.gimp-2.8/scripts/my-process.scm and is invoked with:
gimp -i -b '(my-process "somefile.xcf")' -b '(gimp-quit 0)'
The script appears to run and I get output on the console saying batch command executed successfully. Furthermore, if I put an obvious syntax or parameter error into the script then I get an error. I've also tried re-getting the drawable after the rgb conversion, in case the conversion results in a different object. I've also tried using file-png-save-defaults instead of file-png-save2, to no avail.
However, the output I get is a simple png export in indexed color mode (the original mode of the source image), which does not contain the alpha channel.
I've looked at the documentation for the conversion steps I'm using and cannot figure out what's going on; help would be much appreciated.

This works for me (this is your code in Python, using the same calls):
image=gimp.image_list()[0]
layer=image.active_layer
print "Type before:",pdb.gimp_drawable_type(layer)
pdb.gimp_image_convert_rgb(image)
print "Type after:",pdb.gimp_drawable_type(layer)
print "Has alpha after:",pdb.gimp_drawable_has_alpha(layer)
pdb.plug_in_colortoalpha(image,layer,(0,0,0))
pdb.file_png_save2(image,layer,'/tmp/foo.png','/tmp/foo.png',0,9,1,1,1,1,1,0,1)
And the output is (you can paste the above directly in the Python console):
>> image=gimp.image_list()[0]
>>> layer=image.active_layer
>>> print "Type before:",pdb.gimp_drawable_type(layer)
Type before: 4
>>> pdb.gimp_image_convert_rgb(image)
>>> print "Type after:",pdb.gimp_drawable_type(layer)
Type after: 0
>>> print "Has alpha after:",pdb.gimp_drawable_has_alpha(layer)
Has alpha after: 0
>>> pdb.plug_in_colortoalpha(image,layer,(0,0,0))
>>> pdb.file_png_save2(image,layer,'/tmp/foo.png','/tmp/foo.png',0,9,1,1,1,1,1,0,1)
What I find fishy is that there is no alpha channel after the conversion (type is RGB_IMAGE and not RGBA_IMAGE) (which is expected), but color-to-alpha works without adding one. You can however try to add one explicitly and see if this changes something.
This said, 95% of all batch processing in Gimp is better done with ImageMagick. For color-to-alpha, see this SO question

Related

Gimp 'gimp-image-convert-indexed' produces huge files

I am writing a script (my first script-fu) to export .jpeg to .avif and .webp, and I want to optimize the files for the web. Somewhere I read the suggestion to change from RGB to an indexed color palette, so I implemented the procedure gimp-image-convert-indexed. I was expecting smaller, web optimized files, but the opposite happened. The output resulted in huge files:
Original jpeg: 7.510 KB
Exported files without gimp-image-convert-indexed:
.avif: 95 KB
.webp: 2.052 KB
Exported files with gimp-image-convert-indexed:
.avif: 6.337 KB
.webp: 19.393 KB
Did I sent a parameter wrong? Or is the whole idea of using 'gimp-image-convert-indexed' nonsense?
(Aside: any other obvious flaws in my beginner's script? Comments and hints welcome.)
convert.scm:
(define (filename-basename orig-name)
(car (strbreakup orig-name "."))
)
(define
(convert in_filename WebP Avif)
(let* (
(image (car (gimp-file-load RUN-NONINTERACTIVE in_filename in_filename)))
(drawable (car (gimp-image-flatten image)))
(outWebP (string-append (filename-basename in_filename) ".webP"))
(outAvif (string-append (filename-basename in_filename) ".avif"))
)
; small output files sizes without this line, huge with:
(gimp-image-convert-indexed image CONVERT-DITHER-FS CONVERT-PALETTE-WEB 0 0 1 "")
(cond ((equal? WebP 1)
(gimp-message "exporting as .webP")
(file-webp-save2 RUN-NONINTERACTIVE image drawable outWebP outWebP 0 0 90 100 0 0 0 0 0 0 0 0 0 0)))
(cond ((equal? Avif 1)
(gimp-message "exporting as .avif")
(file-heif-av1-save RUN-NONINTERACTIVE image drawable outAvif outAvif 50 0)))
(gimp-image-delete image)
)
)
Invoke under windows:
gimp-console-2.10 -idf -b "(convert \"IMG.jpg\" 1 1)" -b "(gimp-quit 0)"
Converting to indexed is nonsense since your output format does not support it. Color-indexing may reduce image size on PNG (which is the only format I know with both color-indexed and full-RGB formats).
I don't see much benefit on WebP/Avif over Jpeg, for the same final visual quality. In other words,there are JPEG options that work just as well: reducing quality or increasing chroma sub-sampling.
Also to batch-convert images, ImageMagick is much easier to code around than Gimp.

opencv_createsamples "Assertion Failed" Error

I am trying to create a vec file from my positive image samples. I'm using the latest version of Opencv. The command I am using is this:
opencv_createsamples -info Positive.info -num 3750 -w 24 -h 24 -vec Positive.vec
All my images are bigger than 24x24, so I don't believe that that is the issue. I've tried searching online, but I don't find anyone with this error while doing the createsamples command. The output that I get when I run that is this:
Info file name: Positive.info
Img file name: (NULL)
Vec file name: Positive.vec
BG file name: (NULL)
Num: 3750
BG color: 0
BG threshold: 80
Invert: FALSE
Max intensity deviation: 40
Max x angle: 1.1
Max y angle: 1.1
Max z angle: 0.5
Show samples: FALSE
Width: 24
Height: 24
Max Scale: -1
RNG Seed: 12345
Create training samples from images collection...
OpenCV: terminate handler is called! The last OpenCV error is:
OpenCV(4.0.0-alpha) Error: Assertion failed (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows) in cv::Mat::Mat, file c:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\matrix.cpp, line 465
This is my first time using opencv, so I'm very unclear as to what this error is. Anyone have any experience with this or can point me in the right direction to correcting the error?
This is Priyanka.
I was also getting the same error and I was trying to get resolution to it somehow.
But I could not find anything on internet.
But I am able to solve the problem successfully.
2-3 things that were missing as below:
I used opencv_annotation.exe to generate the -info (text file). This utility embeds complete image path into the file, where as the opencv_createsamples.exe expects that the images are present in the same folder as of the -info file. So what used to happen was the path of the image was getting concatenated with the path of the -info file.
i.e Suppose -info file is available at D:\MyPath\DataSet\annotations.txt and the images are at D:\MyPath\DataSet\Vehicles\*.png. In this case, while executing the opencv_createsamples.exe, the complete image path becomes D:\MyPath\DataSet\D:\MyPath\DataSet\Vehicles\image000.png, which the utility is not able to find.
So cater to the correct path kindly take care of below things
put the -info file in the same path as of images.
ensure that the -info file does not have the path for any image. It should contain only the
<image name without complete path> <object instances> <x y, width height>
With this change the image path was taken correctly and my issue got resolved.
Try doing this. It may help you.
This is Tushar Pathade, this error comes when your info.txt(file which contains information of objects to be detected) file contains some wrong information like image_name 1 0 0 0 0 or image_name 2 10 20 30 40. In first examples coordinates are (0,0,0,0) which is impossible while in second example no. of objects are 2 but coordinates of only one objects are mentioned.
So this lines produced this error. So first remove it and then run. You will not get any error then.
As priyanka mentioned above, this also need to take care of first but this will produced another error. It is nothing but image not found error. So to avoid it put info.txt file in a folder where negative images are. Basically u will see path in error so accordingly handle it.
Thank you.
I got the same error.
The error is about the bounding boxes, sometimes while creating bounding boxes you create a box outside the image pixel so that region is not get accepted and then you get this error.
Solution :
I used divide and conquer tech for this solution. What I did is I've created a new text file and in that text file I pasted some files from the original info or text file I ran the code if its creating samples then good if not then delete any one image from that text file run again*(run the create_samples again)*. do this until you get the clean file. I know this is too tedious task but this works.!
Thanks
I face the same issue now, if the num argument is less than 950 it works for me.

Gimp script-fu working only sometimes

I'm not really one of the graphic savvy people so I kinda hit a wall with this script found on the interwebz
(
define (script-fu-pcb-filter img)
(gimp-image-convert-grayscale img)
(gimp-image-flip img 1)
(gimp-image-resize img (* (cadr (cddr (gimp-selection-bounds 1))) 2) (* (caddr (cddr (gimp-selection-bounds 1))) 2) 0 0)
(gimp-layer-copy 2 1)
(gimp-image-add-layer img 3 0)
(gimp-layer-new img (cadr (cddr (gimp-selection-bounds 1))) (caddr (cddr (gimp-selection-bounds 1))) 2 "druhy" 100 0)
(gimp-image-add-layer img 4 0)
(gimp-edit-fill 4 2)
(gimp-image-lower-layer-to-bottom img 4)
(gimp-image-merge-down img 2 0)
(gimp-selection-all img)
(gimp-flip 5 0)
(gimp-floating-sel-anchor 6)
(gimp-selection-all img)
(gimp-flip 5 1)
(gimp-floating-sel-anchor 7)
(gimp-flip 3 1)
(gimp-image-merge-down img 3 0)
(gimp-convert-indexed img 0 3 0 FALSE FALSE "a")
(file-png-save 1 img 8 "/tmp/etch_eagle_export.png" "/tmp/etch_eagle_export.png" FALSE 9 FALSE FALSE FALSE TRUE FALSE)
)
(script-fu-register "script-fu-pcb-filter"
"PCB-Filter"
"Gets ready export image from egale ready for print"
"Anton Krug "
"Anton Krug"
"2009-04-25"
"RGB*, GRAY*, INDEXED*"
SF-IMAGE "Input Image" 0)
(script-fu-menu-register "script-fu-pcb-filter" "/Image/Eagle/")
It's supposed to flip an image and mirror it so that I get two copies of the same image on one page (A4 destination) and the image should retain it's original proportions i.e. no resize whatsoever. The image will then be printed on a transparency and used to etch a pcb.
I saved the script in the right folder and when I start gimp with a clean data folder (in my case /home/foo/.gimp-2.8) the script runs fine, once. I can't run the script a second time on another image after closing the first image or even after restarting gimp. I have to delete gimp's data folder and re-save it in the scripts folder for the script to run again. This kinda beats the purpose of scripts imho so I was wondering why it's now working as intended. Is there something I'm missing?
Edit: error message & addendum
addendum: the menu item PCB-Filter appears 2x when I refresh the scripts from a fresh profile folder. I'm running manjaro, a derivative of arch linux, and gimp -v gives out:
$ gimp -v
GNU Image Manipulation Program version 2.8.22
git-describe: GIMP_2_8_20-60-ge39a4e1203
using GEGL version 0.2.0 (compiled against version 0.2.0)
using GLib version 2.52.3 (compiled against version 2.52.2)
using GdkPixbuf version 2.36.8 (compiled against version 2.36.6)
using GTK+ version 2.24.31 (compiled against version 2.24.31)
using Pango version 1.40.9 (compiled against version 1.40.6)
using Fontconfig version 2.12.4 (compiled against version 2.12.3)
using Cairo version 1.14.10 (compiled against version 1.14.8)
Regards

OpenCV read image from csv file

I have image in csv file and i want to load it in my program. I found that I can load image from cvs like this:
CvMLData mlData;
mlData.read_csv(argv[1]);
const CvMat* tmp = mlData.get_values();
cv::Mat img(tmp, true),img1;
img.convertTo(img, CV_8UC3);
cv::namedWindow("img");
cv::imshow("img", img);
I have RGB picture in that file but I got grey picture... Can somebody explain me how to load color image or how can I modify this code to get color image?
Thanks!
Updated
Ok, I don't know how to read your file into OpenCV for the moment, but I can offer you a work-around to get you started. The following will create a header for a PNM format file to match your CSV file and then append your data onto the end and you should end up with a file that you can load.
printf "P3\n284 177\n255\n" > a.pnm # Create PNM header
tr -d ',][' < izlaz.csv >> a.pnm # Append CSV data, after removing commas and []
If I do the above, I can see your bench, tree and river.
If you cannot read that PNM file directly into OpenCV, you can make it into a JPEG with ImageMagick like this:
convert a.pnm a.jpg
I also had a look at the University of Wisconsin ML data archive, that is read with those OpenCV functions that you are using, and the format of their data is different from yours... theirs is like this:
1000025,5,1,1,1,2,1,3,1,1,2
1002945,5,4,4,5,7,10,3,2,1,2
1015425,3,1,1,1,2,2,3,1,1,2
1016277,6,8,8,1,3,4,3,7,1,2
yours looks like this:
[201, 191, 157, 201 ... ]
So maybe this tr command is enough to convert your data:
tr -d '][' < izlaz.csv > TryMe.csv
Original Answer
If you run the following on your CSV file, it translates commas into newlines and then counts the lines:
tr "," "\n" < izlaz.csv | wc -l
And that gives 150,804 lines, which means 150,804 commas in your file and therefore 150,804 integers in your file (+/- 1 or 2). If your greyscale image is 177 rows by 852 columns, you are going to need 150,804 RGB triplets (i.e. 450,000 +/- integers) to represent a colour image, as it is you only have a single greyscale value for each pixel.
The fault is in the way you write the file, not the way you read it.
To see color image I must set number of channels. So this code works for me:
CvMLData mlData;
mlData.read_csv(argv[1]);
const CvMat* tmp = mlData.get_values();
cv::Mat img(tmp, true),img1;
img.convertTo(img, CV_8UC3);
img= img.reshape(3); //set number of channels

Image filtering - wrong results?

I'm experimenting with convolving an image with a user-supplied mask, in this case
u = array([[-2,-2,-2],[-2,25,-2],[-2,-2,-2]])/9
using the commands
In[1]: import scipy.ndimage as ndi
In[2]: import skimage.io as io
In[3]: c = io.imread('cameraman.png')
In[4]: cu = ndi.convolve(c,u)
In[5]: io.imshow(cu)
I'm checking this against commands in GNU Octave:
Octave-3.8: 1> c = imread('cameraman.png');
Octave-3.8: 2> u = [-2 -2 -2;-2 25 -2;-2 -2 -2]/9
Octave-3.8: 3> cu = imfilter(c,u)
Octave-3.8: 4> imshow(cu)
But here's the thing: Octave seems to give the correct result, but Python doesn't, even though the commands convolve and imfilter are supposed to be implementing the same algorithm. (Well in fact imfilter performs a correlation, which in this case is the same as a convolution.)
The Octave output is:
!
and the Python output is:
!
which as you can see is very different to the Octave result. Does anybody know what's going on here? Or is there a better way of convolving with a user-supplied linear filter than using convolve?
The problem may be the result of your convolution taking your image luminance values out of bounds. I ran the example below in Matlab (~=Octave) and for an image that initially has grey values 0-255 so in normalised range [0,0.99] the result ends in with pixels in range [-0.88,2.03].
>> img=double(imread('cameraman.tif'))./255;
>> K=[-2 -2 -2 ; -2 25 -2; -2 -2 -2]/9;
>> out=conv2(img,K,'same');
>> max(max(out))
ans =
2.0288
>> min(min(out))
ans =
-0.8776
It could be that Python has a problem visualising images with out of range grey values <0 or >255 and this is causing a clamping of values resulting in black/white halos in those areas. Perhaps Octave normalises the image prior to displaying it resulting in few artifacts. If you normalise you image in Python prior to displaying it, do you still have this problem?

Resources