8
votes

QT a-t-il un moyen de trouver une boîte de sélection d'une image?

Étant donné une image .png avec un arrière-plan transparent, je veux trouver la zone de sélection des données non transparentes. Utilisation de pour boucles avec qimage.pixel () est douloureusement lent. Y a-t-il une méthode intégrée de faire cela dans qt?

qt

0 commentaires

3 Réponses :


5
votes

Il existe une option qui consiste à utiliser un qgraphicspixmapitem et interrogation pour la zone de liaison de la zone opaque ( qgraphicspixmapitem :: opaquearea (). BoundingRect () ). Je ne sais pas si c'est le meilleur moyen mais ça marche :) Il peut être utile de creuser dans le code source de QT pour voir quel code est au cœur de celui-ci.

Le code suivant imprimera la largeur et la hauteur de l'image suivie. Par la largeur et la hauteur des parties opaques de l'image: xxx


5 commentaires

Opadeaaa () construit un chemin entier décrivant la zone. Cela devrait être plus lent que le calcul de rectangle de liaison simple.


Espérons que l'OP peut poster des résultats de synchronisation. Je serais intéressé de voir combien de temps prendre les deux options. Mais oui, pour des images compliquées, je ne peux que l'imaginer que cela soit plus lent.


J'ai fait quelques timbres difficiles de ma tâche sur-toutes tâche sans créer de micro-repère. Cette approche utilisait essentiellement la même quantité de temps d'horloge murale que mes boucles imbriquées, mais a pris moins de temps de processeur.


Merci pour les commentaires et félicitations pour votre nouveau pouvoir de vote :)


Je viens de tomber sur QgraphicspixMapitem à nouveau et j'ai pensé que c'était vraiment sympa que vous l'avez dirigé ici. En outre, si l'on a besoin du trajet d'un QIMAGE ou de QPIXMAP, ils ne trouvent pas facilement que Qt fournit la fonctionnalité de QGraphicsPixMapitem.



4
votes

Si pixel () est trop lent pour vous, envisagez une adressage de données de ligne plus efficace, étant donné un QIMAGE:

int l =p.width(), r = 0, t = p.height(), b = 0;
for (int y = 0; y < p.height(); ++y) {
    QRgb *row = (QRgb*)p.scanLine(y);
    bool rowFilled = false;
    for (int x = 0; x < p.width(); ++x) {
        if (qAlpha(row[x])) {
            rowFilled = true;
            r = std::max(r, x);
            if (l > x) {
                l = x;
                x = r; // shortcut to only search for new right bound from here
            }
        }
    }
    if (rowFilled) {
        t = std::min(t, y);
        b = y;
    }
}


2 commentaires

Ce n'est pas comme si les documents Qt le font la publicité. M'a pris une demi-année pour en savoir plus.


J'ai fait quelques timbres difficiles de ma tâche sur-toutes tâche sans créer de micro-repère. Cette approche utilisait essentiellement la même quantité de CPU-Time que la solution d'Arnold, mais une période de temps murale réduite.



1
votes

La solution la plus facile et relativement rapide est de faire comme suit: xxx

si vous avez un qpixmap plutôt que qimage , Ensuite, vous pouvez utiliser: xxx

qpixmap :: créemaskfromcolor convertira la pixmap en une image et faites la même chose que ci-dessus. Une solution encore plus courte pour qpixmap est la suivante: xxx

dans ce cas, un qpixmap sans canal alpha entraînera un Région vide, vous devrez peut-être vérifier explicitement cela. Incidemment, c'est aussi ce que qgraphicspixmapitem :: opaquearea mentionné par @ARNOLD Spence est basé sur.

Vous pouvez également essayer qimage :: créatealphamask , bien que le point de coupure ne soit pas à 0 alpha mais plutôt quelque part à une demi-opacité.


0 commentaires