NO

Author Topic: Editor for convolutions filters  (Read 4208 times)

Grincheux

  • Guest
Editor for convolutions filters
« on: March 22, 2021, 07:59:39 pm »
I did not know which name to give and I was trying to use Gimp, it is the reason.
The program works with Drag'n Drop only.

The editor can create filters from 3x3 to 19x19.
The resulting image can be saved.
1-File name currently editing : Img 0035.jpg
2-Saved file name (first saved) : Img 0035 - Result.jpg
3-File name when being saved an other time : Img 0035 - Result (0).jpg

Have fun using it.
« Last Edit: April 04, 2021, 09:28:15 am by Grincheux »

Offline John Z

  • Member
  • *
  • Posts: 533
Re: Editor for convolutions filters
« Reply #1 on: March 23, 2021, 10:14:49 am »
Thanks!

I'll play around with it.  Its not going to fill my HD with 1000's of files I hope  :)
A lot of work to do this kind of transformation.
3x3 means 3 pixels in X and 3 pixels in Y ?

John Z

Grincheux

  • Guest
Re: Editor for convolutions filters
« Reply #2 on: March 23, 2021, 02:15:35 pm »
Hello John,

3x3 means 3 rows by 3 colums (3 * 3)

As you know a program never is finished and I have a lot of new ideas.
The biggest difficulty when starting with filters is what to put into each fields.
For example, you create a 19x19 filter.
That means there are 361 fileds.
When filling them the program puts a '1' into the edit fields.
That gives 361 when making the sum.
For having something to see just put -361 int the field 10 on line 10 and click 'Apply'.
Filters are very interesting because we can nice images.
I will store the filters into a database, will add an random option...

That's for the next season... It will not be like 'Dallas'... I hope.

Offline John Z

  • Member
  • *
  • Posts: 533
Re: Editor for convolutions filters
« Reply #3 on: March 24, 2021, 05:04:21 pm »
OK Thanks!

John Z

Grincheux

  • Guest
Re: Editor for convolutions filters
« Reply #4 on: March 25, 2021, 12:40:38 am »
Added two buttons : Inverse and Random
  • If the windows are closed it is possible to reopen them.
  • Hidden edit border fields.
  • When you click on Clear, Set, Randomize or inverse, the program computes the divisor and sets into the middle field.
I have improved the border treatment in creatig a bigger images than the original. In fact I add 25 black pixels all around. This the reason why there is a whit border but all the orignal is modified that was not the case before. I have search how to do for borders, the answer was : "Every one does like he wants, one set black pixel, one compute new colors...'.
« Last Edit: April 04, 2021, 09:27:40 am by Grincheux »

Offline John Z

  • Member
  • *
  • Posts: 533
Re: Editor for convolutions filters
« Reply #5 on: March 25, 2021, 09:44:20 am »
Took a bit to figure out what to select and when but working  :)


John Z

Click on the picture for a better view ….
« Last Edit: March 25, 2021, 09:46:32 am by John Z »

Grincheux

  • Guest
Re: Editor for convolutions filters
« Reply #6 on: March 25, 2021, 02:06:44 pm »
I know that a minmum of documentation is to do...
It is coming ASAP.
Before I have to implement the histogrammes.
The function to compute them is written, just need a little courage for wrtting the display functions.
After I will write an help file.

When you start the program, it creates a filter of 3 rows and 3 colums.
All is at 0 except the central point which indicates the sum of numbers grether than 0.
If you want to fill all the filter with 0, click CLEAR
If you want to fill all the filter with 1, click SET

The RESET button, redraws original image on the two floatting windows.
RANDOMIZE insert randomized value int the filter, except for the central point.
INVERSE compute THE NOT value for all the fileds.
SAVE saves the current file.

Action menu:
View the result window : Creates or bring to foreground the result window. In the case you closed it.
View the Original Window : Creates or bring to foreground the original window. In the case you closed it.

For example, in a 3x3, if all the fields are equal to 1, the divisor is 9.
Using a divisor may result to add a blur on the new image.
For the instant I think I don't do it well.

The version I am correcting, will compute the divisor and it will be possible to force an other value.
At last, many programs add a "Bias" field to modify the luminosity. It seems to the Alpha channel on a image.
That will be done too.

When loading an image, I want to have an histigramme to see how the colors are place on the image. Is the image too dark? That kind of graph can give many answers.

Once the filter applied, an other histogram is computed to see what changed now.

It seems complicated but I will make a big work to explain that.

Thank You for your comments.

For example try
1 0 -2
0 0 0
1 0 -2

this applies the Sobel filter
Save the image.
Load the new image and apply the following filter :

1 0 1
0 0 0
-2 0 -2

Following is a source code to write filters for Sobel, Kirsch and Robinson.
The filter given as a paramerter must be initialized with somle value.
The function initializes the others filters.

Code: [Select]
//   lpFiltre_1 must already be initialized

int Convolve_GetFilters_Sobel(LPCNV_FILTERS lpFilter_1,LPCNV_FILTERS lpFilter_2)
{
   lpFilter_2->Matrix[0] = lpFilter_1->Matrix[0] ;
   lpFilter_2->Matrix[1] = lpFilter_1->Matrix[3] ;
   lpFilter_2->Matrix[2] = lpFilter_1->Matrix[6] ;
   lpFilter_2->Matrix[3] = lpFilter_1->Matrix[1] ;
   lpFilter_2->Matrix[4] = lpFilter_1->Matrix[4] ;
   lpFilter_2->Matrix[5] = lpFilter_1->Matrix[7] ;
   lpFilter_2->Matrix[6] = lpFilter_1->Matrix[2] ;
   lpFilter_2->Matrix[7] = lpFilter_1->Matrix[5] ;
   lpFilter_2->Matrix[8] = lpFilter_1->Matrix[8] ;

   lstrcpy(lpFilter_1->szName,"# Sobel Horz #") ;
   lstrcpy(lpFilter_2->szName,"# Sobel Vert #") ;

   return (TRUE) ;
}


//   lpFilter_W must already be initialized

int Convolve_GetFilters_Robinson(LPCNV_FILTERS lpFilter_W,LPCNV_FILTERS lpFilter_NO,LPCNV_FILTERS lpFilter_N,LPCNV_FILTERS lpFilter_NE,LPCNV_FILTERS lpFilter_E,LPCNV_FILTERS lpFilter_SE,LPCNV_FILTERS lpFilter_S,LPCNV_FILTERS lpFilter_SO)
{
   lstrcpy(lpFilter_W->szName, "# Robinson West #") ;
   lstrcpy(lpFilter_NO->szName,"# Robinson North West #") ;
   lstrcpy(lpFilter_N->szName, "# Robinson North #") ;
   lstrcpy(lpFilter_NE->szName,"# Robinson North East #") ;
   lstrcpy(lpFilter_E->szName, "# Robinson East #") ;
   lstrcpy(lpFilter_SE->szName,"# Robinson South East #") ;
   lstrcpy(lpFilter_S->szName, "# Robinson South #") ;
   lstrcpy(lpFilter_SO->szName,"# Robinson South West #") ;

   lpFilter_NO->Matrix[0] = lpFilter_W->Matrix[3] ;
   lpFilter_NO->Matrix[1] = lpFilter_W->Matrix[0] ;
   lpFilter_NO->Matrix[2] = lpFilter_W->Matrix[1] ;
   lpFilter_NO->Matrix[3] = lpFilter_W->Matrix[6] ;
   lpFilter_NO->Matrix[4] = lpFilter_W->Matrix[4] ;
   lpFilter_NO->Matrix[5] = lpFilter_W->Matrix[2] ;
   lpFilter_NO->Matrix[6] = lpFilter_W->Matrix[7] ;
   lpFilter_NO->Matrix[7] = lpFilter_W->Matrix[8] ;
   lpFilter_NO->Matrix[8] = lpFilter_W->Matrix[5] ;

   lpFilter_N->Matrix[0] = lpFilter_NO->Matrix[3] ;
   lpFilter_N->Matrix[1] = lpFilter_NO->Matrix[0] ;
   lpFilter_N->Matrix[2] = lpFilter_NO->Matrix[1] ;
   lpFilter_N->Matrix[3] = lpFilter_NO->Matrix[6] ;
   lpFilter_N->Matrix[4] = lpFilter_NO->Matrix[4] ;
   lpFilter_N->Matrix[5] = lpFilter_NO->Matrix[2] ;
   lpFilter_N->Matrix[6] = lpFilter_NO->Matrix[7] ;
   lpFilter_N->Matrix[7] = lpFilter_NO->Matrix[8] ;
   lpFilter_N->Matrix[8] = lpFilter_NO->Matrix[5] ;

   lpFilter_NE->Matrix[0] = lpFilter_N->Matrix[3] ;
   lpFilter_NE->Matrix[1] = lpFilter_N->Matrix[0] ;
   lpFilter_NE->Matrix[2] = lpFilter_N->Matrix[1] ;
   lpFilter_NE->Matrix[3] = lpFilter_N->Matrix[6] ;
   lpFilter_NE->Matrix[4] = lpFilter_N->Matrix[4] ;
   lpFilter_NE->Matrix[5] = lpFilter_N->Matrix[2] ;
   lpFilter_NE->Matrix[6] = lpFilter_N->Matrix[7] ;
   lpFilter_NE->Matrix[7] = lpFilter_N->Matrix[8] ;
   lpFilter_NE->Matrix[8] = lpFilter_N->Matrix[5] ;

   lpFilter_E->Matrix[0] = lpFilter_NE->Matrix[3] ;
   lpFilter_E->Matrix[1] = lpFilter_NE->Matrix[0] ;
   lpFilter_E->Matrix[2] = lpFilter_NE->Matrix[1] ;
   lpFilter_E->Matrix[3] = lpFilter_NE->Matrix[6] ;
   lpFilter_E->Matrix[4] = lpFilter_NE->Matrix[4] ;
   lpFilter_E->Matrix[5] = lpFilter_NE->Matrix[2] ;
   lpFilter_E->Matrix[6] = lpFilter_NE->Matrix[7] ;
   lpFilter_E->Matrix[7] = lpFilter_NE->Matrix[8] ;
   lpFilter_E->Matrix[8] = lpFilter_NE->Matrix[5] ;

   lpFilter_SE->Matrix[0] = lpFilter_E->Matrix[3] ;
   lpFilter_SE->Matrix[1] = lpFilter_E->Matrix[0] ;
   lpFilter_SE->Matrix[2] = lpFilter_E->Matrix[1] ;
   lpFilter_SE->Matrix[3] = lpFilter_E->Matrix[6] ;
   lpFilter_SE->Matrix[4] = lpFilter_E->Matrix[4] ;
   lpFilter_SE->Matrix[5] = lpFilter_E->Matrix[2] ;
   lpFilter_SE->Matrix[6] = lpFilter_E->Matrix[7] ;
   lpFilter_SE->Matrix[7] = lpFilter_E->Matrix[8] ;
   lpFilter_SE->Matrix[8] = lpFilter_E->Matrix[5] ;

   lpFilter_S->Matrix[0] = lpFilter_SE->Matrix[3] ;
   lpFilter_S->Matrix[1] = lpFilter_SE->Matrix[0] ;
   lpFilter_S->Matrix[2] = lpFilter_SE->Matrix[1] ;
   lpFilter_S->Matrix[3] = lpFilter_SE->Matrix[6] ;
   lpFilter_S->Matrix[4] = lpFilter_SE->Matrix[4] ;
   lpFilter_S->Matrix[5] = lpFilter_SE->Matrix[2] ;
   lpFilter_S->Matrix[6] = lpFilter_SE->Matrix[7] ;
   lpFilter_S->Matrix[7] = lpFilter_SE->Matrix[8] ;
   lpFilter_S->Matrix[8] = lpFilter_SE->Matrix[5] ;

   lpFilter_SO->Matrix[0] = lpFilter_S->Matrix[3] ;
   lpFilter_SO->Matrix[1] = lpFilter_S->Matrix[0] ;
   lpFilter_SO->Matrix[2] = lpFilter_S->Matrix[1] ;
   lpFilter_SO->Matrix[3] = lpFilter_S->Matrix[6] ;
   lpFilter_SO->Matrix[4] = lpFilter_S->Matrix[4] ;
   lpFilter_SO->Matrix[5] = lpFilter_S->Matrix[2] ;
   lpFilter_SO->Matrix[6] = lpFilter_S->Matrix[7] ;
   lpFilter_SO->Matrix[7] = lpFilter_S->Matrix[8] ;
   lpFilter_SO->Matrix[8] = lpFilter_S->Matrix[5] ;

   return (TRUE) ;
}

//   lpFilter_W must already be initialized

int Convolve_GetFilters_Kirsch(LPCNV_FILTERS lpFilter_W,LPCNV_FILTERS lpFilter_N,LPCNV_FILTERS lpFilter_E,LPCNV_FILTERS lpFilter_S)
{
   lstrcpy(lpFilter_W->szName,"# Kirsch West #") ;
   lstrcpy(lpFilter_N->szName,"# Kirsch North #") ;
   lstrcpy(lpFilter_E->szName,"# Kirsch East #") ;
   lstrcpy(lpFilter_S->szName,"# Kirsch South #") ;

   lpFilter_N->Matrix[0] = lpFilter_W->Matrix[7] ;
   lpFilter_N->Matrix[1] = lpFilter_W->Matrix[3] ;
   lpFilter_N->Matrix[2] = lpFilter_W->Matrix[0] ;
   lpFilter_N->Matrix[3] = lpFilter_W->Matrix[6] ;
   lpFilter_N->Matrix[4] = lpFilter_W->Matrix[4] ;
   lpFilter_N->Matrix[5] = lpFilter_W->Matrix[1] ;
   lpFilter_N->Matrix[6] = lpFilter_W->Matrix[8] ;
   lpFilter_N->Matrix[7] = lpFilter_W->Matrix[5] ;
   lpFilter_N->Matrix[8] = lpFilter_W->Matrix[2] ;

   lpFilter_E->Matrix[0] = lpFilter_N->Matrix[2] ;
   lpFilter_E->Matrix[1] = lpFilter_N->Matrix[1] ;
   lpFilter_E->Matrix[2] = lpFilter_N->Matrix[0] ;
   lpFilter_E->Matrix[3] = lpFilter_N->Matrix[7] ;
   lpFilter_E->Matrix[4] = lpFilter_N->Matrix[4] ;
   lpFilter_E->Matrix[5] = lpFilter_N->Matrix[1] ;
   lpFilter_E->Matrix[6] = lpFilter_N->Matrix[8] ;
   lpFilter_E->Matrix[7] = lpFilter_N->Matrix[7] ;
   lpFilter_E->Matrix[8] = lpFilter_N->Matrix[2] ;

   lpFilter_S->Matrix[0] = lpFilter_E->Matrix[6] ;
   lpFilter_S->Matrix[1] = lpFilter_E->Matrix[7] ;
   lpFilter_S->Matrix[2] = lpFilter_E->Matrix[8] ;
   lpFilter_S->Matrix[3] = lpFilter_E->Matrix[3] ;
   lpFilter_S->Matrix[4] = lpFilter_E->Matrix[4] ;
   lpFilter_S->Matrix[5] = lpFilter_E->Matrix[5] ;
   lpFilter_S->Matrix[6] = lpFilter_E->Matrix[0] ;
   lpFilter_S->Matrix[7] = lpFilter_E->Matrix[1] ;
   lpFilter_S->Matrix[8] = lpFilter_E->Matrix[2] ;

   return (TRUE) ;
}

Some help :

https://en.wikipedia.org/wiki/Sobel_operator
https://en.wikipedia.org/wiki/Laplace_operator
https://en.wikipedia.org/wiki/Prewitt_operator
https://en.wikipedia.org/wiki/Roberts_cross
https://en.wikipedia.org/wiki/Robinson_compass_mask

You can search Nagoa too.
An example of what you can do


and its histogram


That's all for now.
I'm going to take a nap! I am too old...
« Last Edit: March 25, 2021, 02:15:19 pm by Grincheux »

Grincheux

  • Guest
Re: Editor for convolutions filters
« Reply #7 on: March 26, 2021, 08:15:26 am »
Now John, Frankie and the Ghost. A good name for a music group...
I make a pause because I want to test all in depth and would like to speed up the program.
I have an help file to do, it is not easy to do.
I would like to do as wells as John does.
« Last Edit: April 04, 2021, 09:27:14 am by Grincheux »

Grincheux

  • Guest
Re: Editor for convolutions filters
« Reply #8 on: March 28, 2021, 03:41:45 pm »
Here is the last update.
Now I am doing the doc and try to profile the program
« Last Edit: April 04, 2021, 09:26:57 am by Grincheux »

Offline John Z

  • Member
  • *
  • Posts: 533
Re: Editor for convolutions filters
« Reply #9 on: April 01, 2021, 10:42:06 am »
Got it.

Thanks!

Grincheux

  • Guest
Re: Editor for convolutions filters
« Reply #10 on: April 02, 2021, 11:22:22 am »

Here is the last version waiting for doc again.
You can compile/run it but it needs sqlite3:


sqlite3.h
sqlite3.lib
sqlite3.dll
« Last Edit: April 02, 2021, 06:46:18 pm by Grincheux »

Grincheux

  • Guest
Re: Editor for convolutions filters
« Reply #11 on: April 02, 2021, 11:28:30 am »
Here is sqlite3

Offline John Z

  • Member
  • *
  • Posts: 533
Re: Editor for convolutions filters
« Reply #12 on: April 02, 2021, 12:57:51 pm »
Have you considered compiling SQLite directly into the sources?  This way an end user does not need to install an additional package to run your program.   I got it (SQLite) to run within a program I had already written using Pelles C.  The only downside I could see was the final project exe was 2x larger in my test case.


John Z

Grincheux

  • Guest
Re: Editor for convolutions filters
« Reply #13 on: April 02, 2021, 06:48:44 pm »
You found why, too big


Here is the last version with a readme file.
Last SQLite 64 bits version https://www.filehorse.com/download-sqlite-64/download/
« Last Edit: April 04, 2021, 09:26:32 am by Grincheux »

Grincheux

  • Guest
Re: Editor for convolutions filters
« Reply #14 on: April 03, 2021, 10:12:34 am »
For JohnZ

Quote
The program only accept file thru the Drag'n Drop process.
It accepts many image formats. Not only JPEG.
It uses the "Tahoma" font.

Buttons

Result      Shows the RESULT window. If it is closed it is created.
Original   Shows the ORIGINAL window. If it is closed it is created.
Histogram   Shows the HISTOGRAM window. If it is closed it is created.

Compute Divisor   Just an indication for the sum of the filter.
            Attention the value willbe used the next time you click on a button.
            Click the Clear button to set it to 0.

Clear         Sets all the edit fields to 0. Clears Divisor and Bias.
Set            Sets all the edit fields to 1.
Reset         Sets the content of the Original image into the Result image without applying any filter.
Previous 1      Restore the last random filter
Previous 2      Restore the second random filter

Inverse         Inverse (Not) the edit fields content.
Random         Insert random values into the edit fields.
            Copie "Previous 1" to "Previous 2" and copie the current filter into "Previous 1".
            All this is made before anything.

Negative      Negate the output values, not the entire image.
            During the filter operation the RED, GREEN and BLUE values are set to -Red / -Green / -Blue

Save         Saves the filter into the database and creates the output image file.
            If the filter is a model, it is not saved.

Apply         Apply the filter to the orginal image and store the resulting operation into the Result image.

Combos

Sizes         Allow the user to select between different filter sizes.
            All the sizes are Odd, because there is no middle if the size is even.
            For a 5x5 filter the middle is 2. AAMAA

Models         Different models of filters with different sizes allowing to get a quick result.

Divisor         The value stored into this field is divided by the number of columns * numbers of rows.
            The value got will be multiplied to each component once the filter is applied.

Bias         This value is added to each component once the filter is applied.
            To be exact, the program would have to have three bias fields, one for Red, one for Green and one for blue.

Grey         The check boxes are managed as follow
            Grey Input                        Ok
            Grey Input + Grey Output            Ok
            Grey Input + Grey None               KO   The program unchecks the grey input field.
            Grey Output                        OK
            Grey Output + Grey None               KO   The program unchecks the grey output field.
            Grey Input + Grey Output + Grey None   KO   The program unchecks the grey input and output fields.

            if none of the check boxes are checked, the program check the Grey None.

Random         Numbers are generated between -841...+841 (29x29) limit filter size for the program.

Database organisation

The database is named "User Filters.db3" and is created into the program folder.
It is a sqlite database. The VACUUM command is never executed. Take care when the database grows.
It is possible to store twice the same filter!
The database is created if it does not exists, when the program starts.
It is not important if it exists or not.
If it exists the filters will be append. The index used in that case is the biggest plus 1.
The same index "[RecordNumber]" cannot be inserted twice.
The field "[Name]" is filled by the program, but you can change it if you want. Max 63 characters.
The field "[Grey]" must have the values 0, 1, 2 or 3.
The values are stored into the fields "[V001]" to "[V361]". 19x19 filter.

                           "   [NumberOfColumns]   INTEGER DEFAULT 0 COLLATE BINARY,\n"
                           "   [ColsNumber]      INTEGER DEFAULT 0 COLLATE BINARY,\n"

They must have the same value. For a 9x9 filter, the value 9 is stored in the two fields!

Mathenay, le 2 Avril 2021
Philippe RIO / Grincheux
51966@protonmail.ch
France
-----------------------------------------------------
2021-04-03   Added a primary key composed by a CRC64
         The RecordNumber is just an index.
         When saving filter, if that fails, the image is saved.
         Included SQLite 3.35.3 in 64 bits.