Showing posts with label sudoku. Show all posts
Showing posts with label sudoku. Show all posts

Monday, August 17, 2020

SudokuFX Version 2020.3.0

After successfully prototyping a webcam image stream with latest JavaFX goodies my next step for my hobby project SudokuFX is clear - port everything to JavaCV and use it's implementation to speedup SudokuFX.


With version 2020.3.0, I rewrote almost everything; conceptually my application follows the original approach, but the implementation is simpler and yields itself better for future enhancements.


Some highlights:

- SudokuFX uses JavaCV
- got rid of overcomplicated usage of Scala Future's
- improved image recognition by tweaking used templates
- improved visual appearance by a smarter approach to overlaying empty cells with numbers, not replacing them
- better memory and CPU utilisation
- Changed versioning scheme to use revision / changelist
- Upgrade to JavaFX 15-ea+4
- Upgrade to Scala 2.13.3
- many other small improvements and bug fixes ... 

There is one drawback - currently there is no android support anymore in the current version, but I'm trying to reactivate it again (maybe more, but you know how it works for hobby software side projects ... )

I'll describe some of the mentioned points above now in more detail ...

SudokuFX uses JavaCV now ... why?


Let me start with basic project setup, that is to say maven dependencies and stuff you need to get SudokuFX to work. 

Speaking of maven dependencies, this is the major reason why I'm switching from 'pure' OpenCV to JavaCV, since it is somehow - magically - fully mavenized and I can use OpenCV indirectly in my application by using JavaCV APIs. 

No need to compile OpenCV myself, no fiddling around with CMake, just staying in my cozy maven Java dependency world, which should lower the bar to start with this project substantially.

Of course JavaCV imposes certain new rules and approaches for the programmer, you have to adapt a little bit and make yourself acquainted with another API. For this project however it payed off. 

I discovered some spots to improve the image processing. It runs way faster and more reliable now.

On the other hand, one has to be careful not to run in subtle bugs which arise from off heap memory management which is a fancy way to say that you'll get exposed to native code behaviour. 

Anyway, starting point for the rewrite to JavaCV was to use raw data from Mat via ByteBuffers, which I only found in JavaCV's API, not in OpenCV. Maybe I'm right, there is no equivalent for this in pure OpenCV C++ / Java API, maybe someone points me to it. With my current approach I'm quite happy, 2020.3 release runs way faster than any other version of SudokuFX so far :)

No more Scala Futures

Scala has a Future implementation in it's standard lib, but it doesn't have the best reputation. All discussions in the Scala community lately made me rethink my approach, and in the end I realized that this pervasive usage of Scala's Future in my code didn't really speed up things, but only bloated the whole source and made it less understandable. As such I refactored this construct out of the source, with planning to later reintroduce it again after cleaning up structure. But I learned that my problem didn't really profit from Future's, as such they are left out completely at the current state of affairs. I can imagine that I'll reintroduce some parallelism again, but at the moment the algorithm runs faster than before. Maybe I'll come back to it and optimise it more, I don't know.

Improved image processing by adapting templates

I'm using template matching for recognising numbers, no third party library like tesseract for example. This keeps it simple, but is certainly a weak point in the approach. Here the project could profit by using a simple neural net maybe. By tweaking and disambiguating the used templates however SudokuFX is now capable of recognising quite a lot of different fonts, which is great (some fonts however will fail miserably ;-) )

Improved visual appearance


One thing I'm quite fond of is that SudokuFX now overlays the computed solution with the original image, yielding a much better visual appearance of the solved Sudoku. It looks far more advanced than before, which is great. 

Improved resource handling

CPU as well as memory footprint are now far better than they used to be. This was also one of the goals of the refactoring, SudokuFX uses less energy, memory and utilizes CPU far better than before.

Versioning Scheme


A blog post from Axel Fontaine made me curious as to not use maven release plugin anymore, but an approach far simpler - SudokuFX is using this approach now too.

JavaFX 15-ea+4 / Scala 2.13.3


Like I reported in a recent blogpost, I migrated SudokuFX to Java11, which is a LTS version of Java and one of the first releases which where JavaFX was decoupled. JavaFX now lives it's own life - but accidentally - or rather planned - has the same release cycles like Java. 

BUT in my usecase scenario I directly profit from the fact that I can use a 'newer' JavaFX with the Java11 LTS version.

Why? Because at the moment of writing this lines here, I have troubles getting Scala to work with Java13, whereas with Java11 my project runs out of the box. 

Scala 2.13.3 is serving as a good starting point to finally change to Scala3, which will also be an interesting endeavour in the future.

So, to sum up, try it out yourself, use SudokuFX to solve your Sudoku problems, have a look at the code to learn something about Scala or JavaCV or report bugs you'll easily find and participate at github.

Sunday, April 26, 2020

SudokuFX: Migration to Java11 LTS

Better late than never: now I want to migrate SudokuFX to Java11.

Up to version 2020.1.1,  SudokuFX needs a Java Runtime with JavaFX integrated - version 8. Choosing the correct Java version is the first hurdle for the casual internet visitor, very easy to 'do wrong'. Cryptic errors will drive away newcomers, will cost even pro's some time until they realize that the wrong platform is used.

Java != Java

Choosing the wrong Java version is a common problem for beginners, I must admit that it becomes more and more complicated.

Every half year a new Java version is released, with new features, and several organisations provide builds. This is a good thing, the industry has to evolve the platform, and it is good if there exist different sources for Java binaries. Many years of development went into a build process which is now simple enough for the average Bob D. Eveloper to build OpenJDK themselves, which is - considering the details - a huge accomplishment. 

For the rest of us, the question is which version of Java to choose? Oracle is still the place to go if you have much money to buy their licenses and subscriptions. Alternatives can be used from AdoptOpenJDK, Azul and others. To ease the migration costs, LTS versions are maintained for a longer period of time - Java version 11 is the one the industry migrates to at this very moment. 

And even me with my SudokuFX project.

Still one has to keep in mind that everybody is advertising their latest release, as such often the newest runtimes and jdks are downloaded, and projects written for older incarnations of those technologies maybe just don't work. 

If your project has dependencies on libraries which are also only written for a specific version of the JDK the game becomes even more complex. Then, as a Scala User, you have even more troubles since libraries for a specific version of Scala doesn't really work together with a different Scala version ... 

I didn't even mention the modularization effort of the JDK itself, which - only very slowly but in a foundational manner - reinvents the whole ecosystem yet again. 

Don't get me wrong, everything happens because of a perfectly sound reason, but it is not trivial to get everything working, considering all those moving targets. There are also not many engineers around who can really cope with those topics to be honest.

Well. Enough motivation to do the move to Java11, without any JavaFX backed in the java runtime. 

SDK! Man!

To easily switch between Java versions (and jvm based applications like sbt, lein, scala and others) a tool called sdkman exists, which is very handy and lets you download and change used version of Java with a simple command. It's like a package manager, just for specific (java) applications. Highly recommended!

Here is an example of how it looks if you want to change a java version from current one to to the version AdoptOpenJDK provided, Java version 11:

homemac:sudokufx lad$ sdk list java
================================================================================
Available Java Versions
================================================================================
 Vendor        | Use | Version      | Dist    | Status     | Identifier
--------------------------------------------------------------------------------
 AdoptOpenJDK  |     | 14.0.1.j9    | adpt    |            | 14.0.1.j9-adpt      
               |     | 14.0.1.hs    | adpt    |            | 14.0.1.hs-adpt      
               |     | 14.0.0.j9    | adpt    | local only | 14.0.0.j9-adpt      
               |     | 13.0.2.j9    | adpt    |            | 13.0.2.j9-adpt      
               |     | 13.0.2.hs    | adpt    |            | 13.0.2.hs-adpt      
               |     | 13.0.1.hs    | adpt    | local only | 13.0.1.hs-adpt      
               |     | 12.0.2.j9    | adpt    |            | 12.0.2.j9-adpt      
               |     | 12.0.2.hs    | adpt    |            | 12.0.2.hs-adpt      
               |     | 11.0.7.j9    | adpt    |            | 11.0.7.j9-adpt      
               |     | 11.0.7.hs    | adpt    | installed  | 11.0.7.hs-adpt      
               |     | 8.0.252.j9   | adpt    |            | 8.0.252.j9-adpt     
               |     | 8.0.252.hs   | adpt    |            | 8.0.252.hs-adpt     
 Amazon        |     | 11.0.7       | amzn    |            | 11.0.7-amzn         
               |     | 8.0.252      | amzn    |            | 8.0.252-amzn        
               |     | 8.0.202      | amzn    |            | 8.0.202-amzn        
 Azul Zulu     |     | 14.0.1       | zulu    |            | 14.0.1-zulu         
               |     | 13.0.3       | zulu    |            | 13.0.3-zulu         
               |     | 13.0.3.fx    | zulu    |            | 13.0.3.fx-zulu      
               |     | 12.0.2       | zulu    |            | 12.0.2-zulu         
               |     | 11.0.7       | zulu    |            | 11.0.7-zulu         
               |     | 11.0.7.fx    | zulu    |            | 11.0.7.fx-zulu      
               |     | 11.0.5       | zulu    | local only | 11.0.5-zulu         
               |     | 10.0.2       | zulu    |            | 10.0.2-zulu         
               |     | 9.0.7        | zulu    |            | 9.0.7-zulu          
               |     | 8.0.252      | zulu    |            | 8.0.252-zulu        
               |     | 8.0.252.fx   | zulu    |            | 8.0.252.fx-zulu     
               |     | 8.0.232.fx   | zulu    |            | 8.0.232.fx-zulu     
               |     | 8.0.202      | zulu    |            | 8.0.202-zulu        
               |     | 7.0.262      | zulu    |            | 7.0.262-zulu        
               |     | 7.0.181      | zulu    |            | 7.0.181-zulu        
 BellSoft      |     | 14.0.1.fx    | librca  |            | 14.0.1.fx-librca    
               |     | 14.0.1       | librca  |            | 14.0.1-librca       
               |     | 13.0.2.fx    | librca  |            | 13.0.2.fx-librca    
               |     | 13.0.2       | librca  |            | 13.0.2-librca       
               |     | 12.0.2       | librca  |            | 12.0.2-librca       
               |     | 11.0.7.fx    | librca  |            | 11.0.7.fx-librca    
               |     | 11.0.7       | librca  |            | 11.0.7-librca       
               |     | 8.0.252.fx   | librca  |            | 8.0.252.fx-librca   
               |     | 8.0.252      | librca  |            | 8.0.252-librca      
 GraalVM       |     | 20.0.0.r11   | grl     | installed  | 20.0.0.r11-grl      
               |     | 20.0.0.r8    | grl     |            | 20.0.0.r8-grl       
               |     | 19.3.1.r11   | grl     |            | 19.3.1.r11-grl      
               |     | 19.3.1.r8    | grl     |            | 19.3.1.r8-grl       
               |     | 19.3.0.r11   | grl     |            | 19.3.0.r11-grl      
               |     | 19.3.0.r8    | grl     |            | 19.3.0.r8-grl       
               |     | 19.3.0.2.r11 | grl     |            | 19.3.0.2.r11-grl    
               |     | 19.3.0.2.r8  | grl     |            | 19.3.0.2.r8-grl     
               |     | 19.2.1       | grl     | installed  | 19.2.1-grl          
               |     | 19.1.1       | grl     |            | 19.1.1-grl          
               |     | 19.0.2       | grl     |            | 19.0.2-grl          
               |     | 1.0.0        | grl     |            | 1.0.0-rc-16-grl     
 Java.net      |     | 15.ea.20     | open    |            | 15.ea.20-open       
               |     | 14.0.1       | open    |            | 14.0.1-open         
               |     | 13.0.2       | open    |            | 13.0.2-open         
               |     | 12.0.2       | open    |            | 12.0.2-open         
               |     | 11.0.2       | open    |            | 11.0.2-open         
               |     | 10.0.2       | open    |            | 10.0.2-open         
               |     | 9.0.4        | open    |            | 9.0.4-open          
 SAP           |     | 14.0.1       | sapmchn |            | 14.0.1-sapmchn      
               |     | 13.0.2       | sapmchn |            | 13.0.2-sapmchn      
               |     | 12.0.2       | sapmchn |            | 12.0.2-sapmchn      
               |     | 11.0.7       | sapmchn |            | 11.0.7-sapmchn      
 Unclassified  | >>> | 8.0.201      | none    | local only | 8.0.201-oracle      
================================================================================
Use the Identifier for installation:

    $ sdk install java 11.0.3.hs-adpt
================================================================================
homemac:sudokufx lad$  sdk use java 11.0.7.hs-adpt

Now this shell is configured to use Java11. Neat, isn't it? (You also get a taste of how many different variations of Java distributions exist, and the list is surely not complete ... )

I choose AdoptOpenJDK without JavaFX packaging, since I installed and experimented with it already some time ago. 

homemac:sudokufx lad$ java -version
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.7+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.7+10, mixed mode)

In IntelliJ I have to change the used JDK as well of course.

Nice. But what does it need to change for Java11 LTS support?

Here is an enforcer plugin rule to make sure we run at least at Java11 and with a certain maven version:


            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-enforcer-plugin</artifactId>
                <version>3.0.0-M3</version>
                <executions>
                    <execution>
                        <id>enforce-jdk</id>
                        <goals>
                            <goal>enforce</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <requireMavenVersion>
                                    <version>3.6.2</version>
                                </requireMavenVersion>
                                <requireJavaVersion>
                                    <version>11</version>
                                </requireJavaVersion>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>



This rules out already some problems and support tickets which is nice. 

Like mentioned above, I most certainly have to change some dependencies in my poms (my hobby).

A valuable resource for JavaFX is of course openjfx.io. Here you will find simple tutorials to get you up to speed with simple JavaFX projects which you can then use for your apps. They've developed a maven plugin which does almost everything you ever want concerning JavaFX, I hope I have time to look at this in more detail soon.

The company behind this is Gluon, the most active contributor to JavaFX. They work very hard to provide a Java based platform for user interfaces on Desktop, embedded and mobile, which is very valuable for the Java community.

Thanks to them - and others - JavaFX can be used as a 'normal' maven dependency in your project. Which is awesome, from a library developer point of view as well as a user who wants to use it in their next project. 

As such, JavaFX got ripped out from the core JRE, like other elements of the JDK it got modularized in Project Jigsaw. If you want to know more about this go buy this book, thank me later.

We are getting closer to what I actually had to change in SudokuFX - namely introducing new dependencies and throwing out old unsupported ones.



            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-base</artifactId>
                <version>11.0.2</version>
            </dependency>
            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-swing</artifactId>
                <version>11.0.2</version>
            </dependency>
            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-fxml</artifactId>
                <version>11.0.2</version>
            </dependency>
            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-controls</artifactId>
                <version>11.0.2</version>
            </dependency>


In my case, I struggled a little bit with the javafx-swing dependency, since it was not obvious (at the time) it had to be included as well. As you can see I use four javafx maven dependencies.

Along the way I had to get rid of jfxtras and jfxtras-labs, which don't provide builds for Java11, at least I found none. I also got problems with the scala compiler plugins and IntelliJ (I introduced them in my last post), but I need them only occasionally and as such I commented them out again.

So to sum it up, the migration was quite painless, you can have a look at the result on github - version 2020.2 of SudokuFX ....

Thanks again for reading

Thursday, April 23, 2020

ScalaFix SudokuFX

I released a new version of SudokuFX, this time a maintenance release. I some warnings I got from compiling.

To make this a little bit more interesting, I used scalafix and autofix. What are those things?

Scalafix is a compiler plugin on top of Scalameta which helps rewriting source code. It provides a framework which can be used for creating own code rewriting rules as well. Autofix is an example for that - it encodes migration rules specifically for ScalaTest.

After a little bit of maven pom fiddling, autofix is configured for my project. All I needed to do was to add a compiler plugin and an additional plugin in my pluginsection of my root pom.xml:


        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>net.alchim31.maven</groupId>
                    <artifactId>scala-maven-plugin</artifactId>
                    <version>4.3.1</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>compile</goal>
                                <goal>testCompile</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <scalaVersion>${scala.major.version}</scalaVersion>
                        <args>
                        ...
                        </args>
                        <compilerPlugins>
                            <compilerPlugin>
                                <groupId>org.scalameta</groupId>
                                <artifactId>semanticdb-scalac_${scala.full.version}</artifactId>
                                <version>4.3.9</version>
                            </compilerPlugin>
                        </compilerPlugins>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>io.github.evis</groupId>
                    <artifactId>scalafix-maven-plugin</artifactId>
                    <version>0.1.2_0.9.5</version>
                    <dependencies>
                        <dependency>
                            <groupId>org.scalatest</groupId>
                            <artifactId>autofix_2.12</artifactId>
                            <version>3.1.0.0</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </pluginManagement>

Thats it ... more or less.

What is still missing is a configuration for scalafix, which is placed in a file called .scalafix.conf. (Note the '.' at the beginning of the file name). This file should be placed next to the main pom file.

Here is the file how I configured it:

rules = [
  RemoveUnused,RewriteDeprecatedNames,ProcedureSyntax,NoValInForComprehension,LeakingImplicitClassVal,NoAutoTupling
]

The inverted rule name is an autofix rule, which comes with the additional dependency for scalafix-maven-plugin. 

After configuring this, you have to call maven like that:

mvn clean compile test-compile scalafix:scalafix

After that, have a look at your git status, you'll see that many files have changed, and the plugin did what was promised: it rewrote source code, applied trivial but useful transformations. For example, it can remove unused imports out of the box, or rewrite code written in procedural style and many other things.

Scalafix can be extended with own plugins, that means in theory you could implement your own rules, specific to your needs. This enables then automatic rewrites which are not only syntactic (which could also be achieved by clever scripting) but semantic: rewrite rules know about the structure of the code. This helps for automating tasks which otherwise would bind valuable developer time ...

I removed other warnings as well, albeit manually, from the source. By doing that, I got new 'unused imports', which swiftly went away by calling just beforementioned mvn command again while I gazed with amazement to my editor watching the computer doing the work for me.

Here is a list of available scalafix rules - or at least the closest to such a list I could find.


Hope I raised your interest in this amazing tooling, check out how to configure ScalaFix for maven (and try to solve some Sudokus and let me know if it worked ;-))

Sunday, April 19, 2020

SudokuFx revisited

This blog post covers my lazy sunday afternoon where I tried to get my ancient Sudoku project running again.

screen capture of application
(If you wonder why those numbers dance around - depending on what the application recognises different solutions are calculated and presented ... yes it's not perfect ;-) )

Years ago I played around with the idea of solving Sudokus with an algorithm and used JavaFX and OpenCV to do it. Quite an unusual combination, then as it is now - but it wasn't really a bad experience at all. In my view the Java OpenCV API is quite usable, and as such I wanted to prove at least for me that I could get it to run (albeit its far from perfect ;-))

I remember spending hours playing around with different filters and effects, always proud of new things I discovered.

Today, I decided to breathe life again into this project, let's see which problems I'll encounter.

First, getting source code from github still works, my last commit already 4 years ago, zero contributors along all those years, that's what a normal OSS project looks like ;-).

I try to revive it again, just the desktop version of it, leaving the android version on my todo list.

First obstacle I hit is to compile it, OpenCV is missing on my system. OpenCV doesn't have a proper maven integration, there is an ancient issue about this, nobody had the mood or skills to solve it yet. 

Update: I learned that there is somekind of maven integration in the meantime! Great!! Anyway, I build OpenCV from scratch for this article, maybe I'll have a go at the maven build another time.

Step 1 - download and compile OpenCV 4.3.0


First, I want to mention that there are several package mangers which provide prebuilt binaries for OpenCV, homebrew for example. It may well be that this is an option you prefer If you stumbled on this page by googling (seems to be rather unlikely but well).

Ok, in the meantime they reached version 4.3.0 something, I download the zip from here but I'm too dumb to find build instructions ...  No obvious links are neither on the main page nor documentation. (They surely exist but I just didn't see them apparently)

Finally, I found them.


There are numerous steps to follow, you'll need Cmake and quite some time during compilation, educated guesses what to choose, we'll go with defaults for the first try. Unzip it somewhere, I choose

~/custom-builds/opencv-4.3.0/src/ 

since we have the famous 'out of source' build CMake proposes as best practice. This means that there is a dedicated directory for build artifacts.

As such I choose following setup:

~/custom-builds/opencv-3.4.0/src/<actual contents of zip>
~/custom-builds/opencv-3.4.0/target/<here build artefacts will be placed>

I jump to this target directory and execute there following command:

cmake ../src/

... then CMake does it's job, checks for all available goodies found on my system, I pray that the right ones I need are contained, otherwise I will have to configure it and fight the dragons of OpenCV ... again.

... But it seems that I'm lucky, at the end of the cmake output it says something about java bindings, which I'm interested in, as such it should compile it like I want.

What I personally don't want is that it installs itself to some system directory, which will definitely pollute my system and break some stuff already fine tuned there, as such I have to Issue CMake again with a proper parameter:

cmake ../src -DCMAKE_INSTALL_PREFIX=../out

(Pro tip: delete your target directory beforehand completely, thank me later). This would put OpenCv then to a directory:

~/custom-builds/opencv-3.4.0/out/

Like that I can delete it again without any trace.

I'm quite sure I don't need 98% what is going to be compiled, and some magic incantation of CMake or it's configuration would prevent compiling and linking it, but I don't want to go down that road, not today.

After configuring CMake you have to invoke 'make' as well, and do it with full throttle, meaning with some concurrent threads to speed things up (yes, you can get your coffee break since it will take a while).

That said, still being in the target directory, now execute

make -j8

which will use 8 threads to compile OpenCV (takes 5min+ on my machine)

In the meantime, I want to mention it is a huge accomplishment that building from scratch 'just works' for many environments, be it MacOsX, Windows, Linux ... this is much work and should be praised!

Everytime I compile something I'm amazed if it works first time without much hassle.... I've spent already countless hours on resolving build problems, it is a major time drain.

Anyhow, make succeeded, and all build outputs are already somewhere lying in the target dir. But with

make install

everything important for the runtime will be put to the ../out directory.

Specifically, one can find dylibs in the out/lib and out/share/java/opencv4 directory.

Step 2 - Make OpenCV available to Maven


I tried to make this easy, all you have to do is to edit the main pom file and tweak some properties and point to your opencv installation directories. Here is an example configuration:


    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <scala.major.version>2.12</scala.major.version>
        <scala.full.version>${scala.major.version}.10</scala.full.version>
        <opencv.major.version>4.3</opencv.major.version>
        <opencv.full.version>${opencv.major.version}.0</opencv.full.version>
        <opencv.install.path>/Users/lad/custom-builds/opencv-4.3.0/out/</opencv.install.path>
        <opencv.java.jar>${opencv.install.path}share/java/opencv4/opencv-430.jar</opencv.java.jar>
    </properties>

After you've changed those settings to your liking, enter following command:

mvn initialize -Pinstall-opencv -N 

Now you should be ready to go, build the project with

mvn package

It shouldn't take too long, and everything should be set up correctly. OpenCV has many dylibs / dlls, which are referenced in this project, but via maven property filtering and some pseudo magic everything should just work.

You can fire it up via (being in the main directory of the project)

java -jar sudoku-javafx/target/sudoku-javafx-2020.1-SNAPSHOT-jar-with-dependencies.jar

A JavaFx Gui should appear, on the first invocation you maybe have to tell your Os that it is ok to give SudokuFx access to the webcam.

I've blogged about this project in several other blogposts, maybe you want to read them as well.

This post is referencing code state from the 2020.1 resurrection release.

To sum up, compiling OpenCV turned out to be much easier now as it was years ago, only my code was a little bitrotten - still is - but at least it should be easier to get it to run now than it was before this little article.

Thanks for reading!

Wednesday, January 6, 2016

Sudoku Capturer Release 1.7

Hi everyone, I'm happy to announce a new release for my Android Sudoku Solver application.

Refueling ""Spokane Sun God""

This release is mainly a service release, I've polished the source a little bit and made it compatible with current developments on the underlying image processing library, OpenCV.

For this I had to update the application to API Level 21, which makes it incompatible with many devices. I'll see how things will develop here, with the current implementation you will need a rather recent phone with a high quality camera, which support this API level anyways. One advantage now is that I've managed to encapsulate the OpenCV API such that I can reuse it in other apps as well, which is a nice thing.

If you are interested in the details, have a look at the source code on github. The application is also an example how to develop image processing algorithms on a desktop environment (using JavaFX) and reusing the code then on a mobile device. Like this you save yourself much development time.

Give it a try and let me know what you think. You can download it for free on the google play store

Encapsulate OpenCV 3.1 as Android AAR

In this post I describe how to encapsulate OpenCV as an Android AAR package such that it is easier to include it as a maven dependency.

[High Street, Guildford, England]  (LOC)


Disclaimer: Apparently there exist many other tutorials about OpenCV, my approach is a little bit unconventional. I also have to mention that there is a very well maintained library called JavaCV which does essentially the same.

The motivation for this blog post is that I want to have an convenient way to use OpenCV with my Android applications. Below I describe what I had to do to achieve this.

Step 1: Download the OpenCV library


On www.opencv.org there is a link to download the library for Android. Download it, unpack it.

If you've followed the post about compiling OpenCV yourself, you already have a directory in your
homedirectory somewhere:

opencv/
opencv/opencv-3.1/
opencv/build/

now, add the unpacked Android SDK:

opencv/
opencv/opencv-3.1/
opencv/build/
opencv/OpenCV-android-sdk-3/

You'll find the usual suspects in the directory, some samples, javadoc for the API, already pre build apk's:

apk/
samples/
sdk/

Now I want to discuss briefly the contents of those directories.

Directory apk: OpenCV Manager

OpenCV encourages you to use a separate application called OpenCV Manager which sole purpose is to make sure you have installed a compatible OpenCV library on your phone. This approach is fine but requires your users to install a second app on their phone. For the technical inclined this is no problem, but for end users this may seem a little bit awkward. I prefer to deliver a self contained app which has no apparent third party dependencies.

The apk directory contains this Manager application for environments where you don't want to use the OpenCV Manager from the play store.


Directory samples: OpenCV Android Samples


The samples directory contains several example apps which demonstrate various aspects of the OpenCV API for android.

./samples/example-15-puzzle.apk
./samples/example-camera-calibration.apk
./samples/example-color-blob-detection.apk
./samples/example-face-detection.apk
./samples/example-image-manipulations.apk
./samples/example-tutorial-1-camerapreview.apk
./samples/example-tutorial-2-mixedprocessing.apk
./samples/example-tutorial-3-cameracontrol.apk

I recommend to install some of the apk's on your device:

  adb install <example.apk>

This is the best way to get a feeling what can be done with the OpenCV Android API, so I suggest to play around with the samples. The source code for those samples is also included.

Directory sdk: Android OpenCV Java API

Here you'll find what you will need for your own app. There are  pre-built android libraries for various architectures and one java API to use the native code. The directory structure you'll find on the top of this directory looks like follows:

etc/ ... some configuration for special routines you could use 
java/ ... the java glue code you will program against
native/ ... prebuilt binaries for the android platform

Since I use maven for most of my projects and all of my open source stuff, I need some way to use the provided java glue code and the binaries in my projects. As long as you just use the default API for OpenCV, you can take the code provided almost off the shelf.

Create an OpenCV AAR ready to use with Maven

The following approach shows how you can create a maven module containing the OpenCV bindings - thanks to the android-maven-plugin it can then be used like a 'normal' maven dependency. The plugin will take care about including the AAR in the final APK, you just have to declare it as a dependency (see below).

For this to happen, I've restructured the source code in the following way:

Restructuring of the sdk subfolder
This is the default structure which works together with the android-maven-plugin and includes only code and binaries you'll need at runtime. The pom looks as follows:

pom.xml for an opencv aar

You can see that I'm referring to the standard android api of a certain version - this is needed in order to properly compile the OpenCV Java API.

In order to get the standard android api, you have to clone yet another project named maven-android-sdk-deployer and install the proper API level in your local maven repository. This can be done for
example by issuing following command:

mvn install -P 5.0

A prerequisite for this command to finish successfully is however that you have already installed the Android SDK itself.

Hint: It seems that the OpenCV 3.1 bindings for Android need at least API level 21, maybe you save some time by just downloading this API Level.

Anyway, if you look closely at the pom.xml you'll notice it is using a custom packaging method, namely 'aar' - this is possible since the android-maven-plugin provides the capabilities for maven to properly create such a file type.

Aar's are bundles which contain libraries (Java code, resources or native code) ready to use in Android Applications. Luckily, android-maven-plugin makes it possible to use aar's like normal maven dependencies.

By using this approach you can deploy the OpenCV bindings in your maven repository. OpenCV can then be treated like any other maven dependency, which is a nice thing.

To recap:

After a successful deploy or local install of this maven module (with mvn install) all you need is to include it in the dependency list of your main app, just like shown below:

dependency declaration for your homebrew opencv maven module

That's all there is to it - you should be able now to use OpenCV in your project. Of course, the maven coordinates change depending on which you've chosen before.

One nice aspect is that the download of the OpenCV Manager is not needed anymore. The drawback is of course that your apk is getting bigger - nothing comes without a price.

For a complete example have a look at the SudokuFX project. Thanks for reading.


Sunday, June 21, 2015

Sudoku Capturer Release 1.6

Sudoku Capturer presents itself now as a self contained app, without the need of OpenCV Manager as a separate download.

Carter Buton Album Loan_00115
From a album belonging to barnstormer/daredevil Carter Buton.

I've decided to use the possibility to integrate OpenCV as a native library without the OpenCV Manager functionality since it improves dramatically the user experience for the application.

Many people had been asking themselves why a "third party" dependency had to be installed for the Sudoku Capturer application, and thus I've decided to go the "deprecated" road and link the OpenCV libraries "statically".

In retrospect I should have done this much earlier, since I've learned that I don't have to include every static lib which is offered by OpenCV, I get away with only a subset of those libraries, and the download is in sum even smaller than with the OpenCV Manager.

Since OpenCV is the only native library I need it suffices to copy the libs to the appropriate place and thankfully the android maven plugin does the rest. Sudoku Capturer supports with armeabi-v7a architecture.

About Sudoku Capturer


Sudoku Capturer is an app to solve Sudokus by using your mobile phone camera. The app uses OpenCV and and Scala, and runs on Android. Furthermore a testbed exists which targets JavaFX on the desktop which makes the development process and debugging of the image processing part much more practical than the typical mobile development workflow would ever permit. The whole source code is hosted on GitHub and can be used for your own experiments.


Saturday, May 17, 2014

Sudoku Capturer 1.4

Today I released a new version of my Sudoku solver app for Android.

Sudoku Capturer 1.4 with incremental number detection

From a user perspective, the most prominent new feature is that the app now shows incremental progress of the numbers which were recognized successfully. This fixes one of the biggest problem with the approach the application had before - numbers which were identified erroneously and which led to a deadlock in the solving algorithm itself.

Currently, on each frame the application makes a quick sanity check if a number would violate the basic rules of the sudoku game - that is to say if at a given cell for example the number seven would be identified, the application now checks if there is already a seven in the same row, column or section. If yes, the whole Sudoku is rendered invalid and the detection algorithm starts from scratch.

In older versions of the application, only one frame of the video stream would be the input for the solving algorithm, which frequently led to non terminating behavior of the solving algorithm itself.

The application is now counting how often a certain number is recognized for a given cell, and after hitting a certain threshold the probability that the detection was correct is certainly higher than without using this simple strategy.

Furthermore, if the Sudoku Capturer app is not able to build up a library of all number from 1 to 9 it paints the number with a internal font - this should happen only very rarely, though.

Give it a try on on your android device, I would be interested in your feedback.

You can download the Sudoku Capturer application in the play store:

Monday, February 24, 2014

Sudoku Solver - on Android

I've ported my Sudoku application now to Android - here is the proof:

You can download it from the play store and support me and my blog by clicking like crazy on the ads! Go for it!!!

Here is what you get: