Pour mettre au point un petit annotateur graphique d'image (placement de symboles graphique, différents mode de sélection de patch), j'utilise Apache Batik.
Cela me permet de contenir les annotations en
SVG, ce qui est bien pratique, autant pour la gestion en interne des annotations (e.g. les layers sont des groupes de symboles graphiques dont la propriétés
SVG visibility change), un arbre
XML c'est la panacée.
J'avais déjà travaillé un peu là dessus, mais c'était codé à la va-vite et uniquement pour afficher les annotations LabelMe:
C'est ainsi que je me suis frotté aux obscurs rouages du pipeline graphique de Batik... et un petit problème que je viens de résoudre est celui-ci:
Si un objet JSVGCanvas est dans le viewport d'un JScrollPane, comment positionner une texture de rendu sur le background du JSVGCanvas (i.e. positionner un background particulier sur l'objet qui est dans le viewport du JScrollPane ! ).
Il faut faire attention à ce que fait la méthode de rendu
paint(...) de JSVGCanvas. En fait, cette méthode
paint(...) est héritée de JComponent:
Un objet JSVGCanvas est un JComponent qui contient une liste de CanvasGraphicsNode. Positionnner un background sur JSVGCanvas, revient à positionner un background sur un JComponent, et la méthode paintComponent(Graphics g) est redéfinie dans la classe JGVTComponent, c'est donc dans cette classe que l'on doit faire quelque chose.
Il n'y a rien de prévu pour cela dans Batik, la solution que j'ai mise en place est de modifier les sources, ça se fait facilement en modifiant la classe org.apache.batik.swing.gvt.JGVTComponent:
private TexturePaint texpaint;
public void setTexturePaint(TexturePaint texpaint){
this.texpaint = texpaint;
}
/**
* Paints this component.
*/
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
Rectangle visRect = getRenderRect();
g2d.setComposite(AlphaComposite.SrcOver);
//les deux lignes suivantes sont commentées.
//g2d.setPaint(getBackground());
//g2d.fillRect(visRect.x, visRect.y, visRect.width, visRect.height);
//et on ajouter les deux lignes suivantes:
g2d.setPaint(texpaint);
g2d.fillRect(0, 0, getWidth(), getHeight());
if (image != null) {
if (paintingTransform != null) {
g2d.transform(paintingTransform);
}
g2d.drawRenderedImage(image, null);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
Iterator it = overlays.iterator();
while (it.hasNext()) {
((Overlay)it.next()).paint(g);
}
}
}
Rien de bien sorcier: on ajoute de quoi positionner un TexturePaint, et on modifie un brin paintComponent(Graphics g) pour texturer le panel plutôt que peindre avec la couleur de background.
that's it !
- netpbm est une bibliothèque de processus de traitement d'image à l'instar de ImageMagick, mais sous la forme de filtre unix.
Sous Ubuntu, la compilation nécessite le paquet libsvga-dev (apporte à des programmes en console la capacité de traiter des ressources graphiques, donne un accès au hardware video). Attention également à correctement positionner libX11.so pendant le script de configure.
- pour compter le nombre de champ d'une ligne via un délimiteur en particulier:
echo $line |tail -1 |awk '{print NF}'
- un script Greasemonkey pour désactiver l'effet de fade in sur la page Google: http://userscripts.org/scripts/show/63436
Depuis quelques jours, je m'intéresse à de la génération automatique d'une hiérarchie de topics en utilisant Flickr.
Pourquoi Flickr ? pour ses données textuelles (le tagging social des images par les utilisateurs du website) et ses données images. J'intègre tout cela à mon modèle de donnée pour construire des collections d'image, et j'explore ces collections avec des outils que j'ai développé il y a quelques mois, je voudrais pouvoir explorer facilement le dataset et gérer les documents (retrait d'image ou de tag).
C'est ainsi que comparativement à mes autres expérimentations, le modèle textuel associé à mes images contient:
- des documents faiblement taggés (weakly tagged).
- des informations textuelles qui ne sont pas forcément en anglais, ni basé sur un alphabet latin.
Jusqu'à présent mes images étaient annotées en anglais et avec l'objectif explicite de construire un jeu de donnée image pour la vision par ordinateur, on peut donc dire que ses images étaient annotées par des
iconographes de l'ordinaire en le sens que les annotations sont pertinentes (i.e. fiable, c'est pour cela que je dis
iconographe) et portent sur des objets de la vie de tous les jours (d'où
iconographe de l'ordinaire).
Le sujet de ce billet est le second point, Java gère très bien l'UTF, mais il est évident que l'index des fonts disponibles pour les UI graphique est délégué à l'installeur de Java sur la machine, car on ne peut pas localiser les fonts de façon standard pour tous les
OS pour lesquels Java est disponible.
Sur ma machine, j'installe toujours Java à la main, dans
/opt, je trouve cela plus propre, je suis contre ce qui est fait pour java-6-openjdk par exemple (mettre les fichiers de configuration de Java dans
/etc... pourquoi vouloir complètement intégrer Java à l'
OS, je trouve que c'est particulièrement microsoftien comme façon de faire... ).
Le fichier
~jrehome/lib/fontconfig.properties qui renseigne Java sur les fonts disponibles sur le système n'est donc pas renseigné quand on installe Java à la main: dans le cas d'Ubuntu il suffit de piocher le fichier installé pour java-6-openjdk
/etc/java-6-openjdk/fontconfig.properties et le copier dans
~jrehome/lib/fontconfig.properties.
Pour rédiger du LaTeX sous GNU/Linux, j'ai longtemps utilisé le plugin pour Eclipse TeXlipse, mais il y a pas mal de bugs dans ce dernier, je suis en train de switcher vers Gedit et son plugin GeditLaTeXPlugin qui est vraiment bien, plus agréable à utiliser, et de plus apporte une visualisation intégrée du pdf.
Cependant, le plugin utilise par défaut
rubber pour automatiser la compilation des documents, ce qui m'embête car je n'arrive pas générer des pdf avec index en utilisant rubber (je n'y arrive que en utilisant pdflatex), c'est ainsi que j'utilise ma propre chaine de compilation pour le plugin.
Ma chaîne de compilation Latex avec Gedit:
/usr/bin/pdflatex -interaction=nonstopmode --src-specials "$filename"
/usr/bin/bibtex "$shortname"
/usr/bin/pdflatex -interaction=nonstopmode --src-specials "$filename"
/usr/bin/makeindex "$shortname.nlo" -s nomencl.ist -o "$shortname.nls"
/usr/bin/pdflatex -interaction=nonstopmode --src-specials "$filename"
gnome-open "$shortname.pdf"
Avec l'option
must succeeded == true à toutes les commandes
sauf pour la commande
bibtex (dans le cas où le bibtex est vide et pas de citation dans le fichier tex, voir plus bas dans ce post).
Quelques difficultés avec pdflatex que j'utilise depuis que je suis sous gedit pour écrire mon latex:
- pour des raisons obscures je n'arrive pas à générer l'index pdf avec autre chose que
pdflatex...
pdflatex n'aime pas les chemins de fichier contenant des caractères accentués.
bibtex retourne une erreur quand le fichier bibtex est vide et aucune citation dans un fichier tex.
UPDATE 2010.01.18:
Le contenu du répertoire du plugin (a coller dans
~/.gnome2/gedit/plugins/GeditLaTeXPlugin),
gedit.plugins.GeditLaTeXPlugin.tar.
La dernière version en date du plugin LaTeXPlugin-0.2rc3.tar.gz, contient comme les précédentes un gros bug de
GUI dans la définition des chaines de compilation: lors de la modification de la chaine de compilation d'un tool (les tools sont les commandes spécifiques de compilation, par exemple
LaTeX -> PDF, ou
LaTeX -> PS) via les
GUI suivantes:

Dans la première fenêtre, celle de gauche, on ne peut modifier effectivement que le premier élément de la liste, dans tous les cas c'est dans le premier élément de la liste que la nouvelle configuration est enregistrée, que l'on ai tenté de modifier le premier tool ou un autre de la liste. Ce qui est plutôt embêtant !
La solution est de modifier à la main le contenu du fichier
~/.gnome2/gedit/plugins/GeditLaTeXPlugin/tools.xml dont le formatage est assez simple.
- De l'annotation automatique sur Flickr avec le Blind Astrometry Server, (un robot web pour annoter automatiquement des images), http://astrometry.net/: cela date du début de l'année 2009, sur des photographies du ciel nocturne du groupe Flickr astrometry, détection et ajout d'annotations pour les astres répertoriés (planètes, galaxies, nébuleuses etc.) via astrometry.net.
C'est un projet très intéressant, les bots pour l'annotation automatique des images reste encore quelque chose de nouveau !
- De la CBIR sur Bing.
Le plugin Silverlight est nécessaire pour utiliser cette fonctionnalité du moteur Bing, ce qui est absolument ridicule car il semble que Silverlight n'est utilisé que pour faire du rendu eye-candy avec des effets de gloss, blend et des miniatures d'image (thumbnails) flottantes...
- Un nouveau Google Labs, Google Image Swirl, sur la recherche d'image itérative avec une navigation dans une hiérarchie de clusters.
Flash et Javascript sont nécessaires pour utiliser l'interface, et contrairement à la fonctionnalité Visual Search de Bing cité plus haut qui nécessite Silverlight, utiliser du Flash dans Google Image Swirl se justifie complètement, il y a une interface pour l'exploration des résultats qui n'est pas un simple listing des image-résultats.
D'après Google, Image Swirl réalise deux opérations: (1) l'organisation des résultats de la recherche d'image sur la base de mesures de similarité visuelle et sémantique entre document, et (2) présentation des résultats organisés dans une interface d'exploration.
screenshot d'une navigation dans Google Image Swirl pour la requête "Pablo Picasso".
Google propose des requête-exemples attaquant le problème de la polysémie telle que "apple", "beetle", "jaguar", et d'autres requêtes attaquant le problème de la perspective visuelle.
D'après le Official Google Blog, Google Image Swirl utilise et étend les technologies développées pour Picasa Face Recognition et Google Similar Images, pour réaliser le grouping des images et la construction de la hiérarchie de clusters.
Remarque 1:
L'utilisateur naviguant de cluster en cluster, une succession d'interactions utilisateur dans une recherche d'image est ainsi une hiérarchie de clusters.
Lorsque l'utilisateur affiche un cluster qui n'a pas de cluster fils (i.e. on ne peut pas construire de nouveaux cluster à partir d'un des documents contenus dans le cluster courant), les résultats sont souvent des plus proches duplicata (near duplicates).
Remarque 2:
Quelque chose qui serait réellement intéressant, bluffant en réalité car c'est un problème très difficile, c'est de justifier une relation entre deux documents dans une navigation dans Google Image Swirl.
Google dit que pour calculer les clusters, ils utilisent des mesures de similarités visuelle et sémantique, nous pourrions vouloir savoir pourquoi google dit que deux documents sont liés: est-ce une prédominance de la similarité visuelle ? une prédominance de la similarité sémantique ? une expansion sémantique ? est-ce deux documents appartenant à une même thématique selon une taxonomie reconnue autour de laquelle il y a consensus ? est-ce deux documents liés via une relation related-to (co-occurrence statistique) ?