Vous pouvez le faire avec Python! Analyse structurale de cristaux colloïdaux bidimensionnels

introduction

Dans cet article, nous effectuerons l'analyse suivante à l'aide d'une image cristalline colloïdale bidimensionnelle.

  1. Détection de la position colloïdale
  2. Dérivation de la fonction de distribution radiale (similaire)
  3. Compter et tracer le premier atome de proximité
  4. Visualisation des grains de polycristal en utilisant l'angle de coordination des atomes proches comme indice

J'ai utilisé les images colloïdales suivantes: miam:

800px-ColloidCrystal_10xBrightField_GlassInWater.jpg Auteur Zephyris [CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0) ou GFDL (http://www.gnu.org/copyleft/fdl.html)], [Wikimedia Depuis Commons (lien)

Liste des bibliothèques à utiliser

C'est comme suit.

import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from scipy import ndimage as ndi
from sklearn.neighbors import NearestNeighbors

Détection de la position colloïdale

Un filtre maximum est utilisé pour détecter la position colloïdale. Cette méthode fait à peu près la même chose que Find Maxima d'ImageJ (https://imagej.nih.gov/ij/docs/menus/process.html#find-maxima).

Tout d'abord, chargez l'image comme indiqué ci-dessous et convertissez-la en échelle de gris. Obtenez également la taille de l'image.

#Chargement d'image
img_raw = cv2.imread('ColloidCrystal_10xBrightField_GlassInWater.jpg', 1)
#Échelle de gris
img = cv2.cvtColor(img_raw, cv2.COLOR_BGR2GRAY)
#Hauteur de l'image,Obtenir la largeur
h, w = img.shape[:2]

Détection de particules à l'aide d'un filtre de valeur maximale

Comme son nom l'indique, le filtre de valeur maximale est un filtre qui fait référence à la luminosité maximale dans une certaine plage autour du pixel d'intérêt. En utilisant cela, il est possible de détecter la valeur maximale locale de l'image, c'est-à-dire la position des particules colloïdales.

Appliquons le filtre avec la taille de la plage d'attention (noyau) définie sur 9x9. (Aucun bruit n'est éliminé par lissage avant application)

#Brouiller(Lissage)Élimination du bruit par
img = cv2.blur(img,(3,3))
#Appliquer le filtre maximum
img_max = ndi.maximum_filter(img, size=9, mode='constant')

Voici une comparaison des images avant et après l'application du filtre. fig1.png

Dans ces deux images, la position où la valeur de luminosité est la même ** est la valeur maximale locale, c'est-à-dire la position de la particule. (Référence) Cela peut être facilement déterminé en utilisant numpy.where.

#Extraction de la valeur maximale locale
pts_list = np.where(img == img_max)
pts_list = np.array(pts_list)

#Tracer sur l'image d'origine
fig = plt.figure(dpi=150,facecolor='white')
plt.gray()
plt.imshow(img)
plt.scatter(pts_list[1],pts_list[0],s=3,c='red',alpha=0.7)
plt.xlim(0,300)
plt.ylim(0,300)

Les points ainsi obtenus sont affichés au-dessus de l'image d'origine et indiqués ci-dessous. fig2.png

Vous pouvez détecter approximativement la position des particules. Cependant, certaines particules ont été détectées deux fois. Afin de supprimer cela, nous allons résumer les points qui sont proches les uns des autres avec leur centre de gravité comme représentant.

Supprimer les points en double

Utilisez sklearn.neighbors.NearestNeighbors pour calculer la distance entre les points.

nbrs = NearestNeighbors(n_neighbors=10, algorithm='ball_tree').fit(pts_list.T)
distances, indices = nbrs.kneighbors(pts_list.T)

Nearest Neighbor renvoie la distance au point de proximité et l'index en spécifiant le nombre de points de proximité.

Cette fois, nous calculerons que les points existant à moins de 3 pixels sont dérivés de la même particule.

#Seuil de proximité
th = 3

#Calculez le centre de gravité avec un point de proximité en dessous du seuil.
center_list = []
for d,i in zip(distances,indices):
    i = i[np.where(d < 3)]
    pts = pts_list.T[i]
    center = np.mean(pts,axis=0)
    center_list.append(center)
center_list = np.array(center_list).astype(np.int32)

#Supprimer les doublons
center_list = np.unique(center_list,axis=0)
center_list = center_list.T

Les points ainsi obtenus sont présentés ci-dessous de la même manière. fig3.png Les points qui se chevauchent dans une particule sont résumés. Ceci termine la détection des particules: thumbsup :: thumbsup:

Dérivation de la fonction de distribution radiale (comme)

Ensuite, nous dériverons la fonction de distribution radiale (RDF). RDF indique la probabilité qu'une autre particule existe par rapport à la distance d'une particule, et est souvent utilisé pour décrire la structure périodique d'un cristal.

Voir ci-dessous pour la dérivation de RDF et sa méthode de calcul. Calcul de la fonction de distribution radiale - Page de Koishi

Utilisez sklearn.neighbors.NearestNeighbors utilisé précédemment pour calculer les atomes de proximité.

#Calculez la position et la distance des atomes proches jusqu'à 40
nbrs = NearestNeighbors(n_neighbors=40, algorithm='ball_tree').fit(center_list.T)
distances, indices = nbrs.kneighbors(center_list.T)

#Calculez la distance par rapport aux autres particules existant à moins de 50 pixels et créez un histogramme
dist_list = []
for d,i in zip(distances,indices):
    d = d[np.where(d < 50)][1:]
    dist_list.extend(d)
dist_list = np.array(dist_list)
dist_hist = np.histogram(dist_list,range=(0,50),bins=50)

#Calcul RDF
rdf = dist_hist[0]/(4*np.pi*np.power(dist_hist[1][1:],2))

Tout va bien. Cette fois, j'ai calculé le RDF dans une plage allant jusqu'à 50 pixels. (Strictement différent car il n'est pas divisé par la densité à la fin, mais cette fois c'est OK si la valeur de crête est connue)

Le résultat est présenté ci-dessous.

fig4.png

Vous pouvez voir les sommets jusqu'à la 1ère, 2ème et 3ème proximité. Les cristaux colloïdaux sont cette fois densément tassés, mais en raison de certains défauts, les pics sont fendus ou larges.

Pour le moment, il s'avère que la distance à la première particule de proximité est d'environ 10 à 18 pixels.

Comptons maintenant le nombre de ces premières particules de proximité.

Comptage et tracé du premier atome de proximité

Lorsque le colloïde sphérique est densément compacté en deux dimensions, le nombre de coordination avec la première particule de proximité est de ** 6 **. La zone en dessous est celle où les colloïdes ne sont pas correctement disposés. En d'autres termes, le traçage du nombre de premières particules de proximité peut illustrer des défauts dans les cristaux colloïdaux.

Faisons-le: v :: v: J'utilise également sklearn.neighbors.NearestNeighbors. Le seuil pour le considérer comme le premier atome de proximité est de 16 px.

#Compter le premier atome de proximité
co_list = []
for d,i in zip(distances,indices):
    d = d[np.where(d < 16)][1:]
    co_list.append(d.shape[0])

De plus, la figure ci-dessous montre le nombre de premières particules de proximité dans un histogramme. ダウンロード.png

Le nombre de particules les plus proches est généralement réparti entre 3 et 7. Pour l'instant, traçons dans l'intervalle (3,6).

fig = plt.figure(dpi=150,facecolor='white')
plt.imshow(img)
plt.scatter(center_list[1],center_list[0],s=3,c=co_list,cmap='rainbow',alpha=0.7)
plt.colorbar()
plt.clim(3,6)
plt.xlim(0,1000)
plt.ylim(0,1000)

fig5.png

L'image d'origine est affichée à gauche et le tracé de chaque particule codée par couleur par coordination est affiché à droite. Partie désordonnée = L'emplacement du défaut peut être illustré: heart_eyes :: heart_eyes:

Enfin, voici un tracé sur toute l'image d'origine: point_down: fig9.png

Visualisation des grains de polycristal en utilisant l'angle de coordination des atomes voisins comme indice

Enfin, visualisons les grains polycristallins de cristaux colloïdaux. Plus précisément, la cartographie bidimensionnelle des grains cristallins (voir la figure ci-dessous) telle qu'obtenue par EBSD (diffraction de rétrodiffusion par faisceau d'électrons) est également effectuée pour les cristaux colloïdaux.

img_m1303_02.gif (Source: https://www.ube-ind.co.jp/usal/documents/m1303_550.htm)

Une telle analyse est également réalisée dans un papier sur des cristaux colloïdaux.Par exemple, sur la figure 1 de l'article suivant, le vecteur formé par la particule d'intérêt ⇒ la première particule de proximité est classée selon l'angle formé par l'axe X, et le grain cristallin est analysé. Nous faisons de la visualisation.

Référence: [Ramananarivo, S., Ducrot, E. & Palacci, J. Recuit à activité contrôlée de monocouches colloïdales. Nat Commun 10, 3380 (2019).](Https://doi.org/10.1038/s41467-019- 11362-y)

Visualisons-le de la même manière!

theta_list = []
for d,i in zip(distances,indices):
    #Extraire les particules de proximité en s'excluant
    idx = i[np.where(d < 16)][1:]
    cnts = center_list.T[idx]
    #Obtenez la position de la particule avec la plus grande valeur X
    top = cnts[np.argmin(cnts[:,1])]
    #Obtenez la position de la particule d'intérêt
    center = center_list.T[i[0]]
    #Calculez l'angle avec l'axe X
    axis = np.array([0,center[1]])
    u = top - center
    v = axis - center
    c = np.inner(u, v) / (np.linalg.norm(u) * np.linalg.norm(v) + 1e-99)
    a = np.rad2deg(np.arccos(np.clip(c, -1.0, 1.0))) - 90
    theta_list.append(a)

L'histogramme des angles ainsi obtenu est illustré ci-dessous.

fig6.png

L'angle semble être dans la plage de ± 30 degrés. Tracons! fig7.png

L'image d'origine est affichée à gauche et l'angle du premier atome de proximité est codé par couleur et tracé sur la droite. Enfin, faisons ce codage couleur pour l'image entière! fig8.png Vous pouvez clairement voir le grain du cristal colloïdal: yum :: yum: Je pense que c'est plus bruyant que la cartographie des journaux auxquels j'ai fait référence, mais c'est assez bon pour un travail de défaite.

Faites appel à vos rivaux avec des personnages colorés!

finalement

Récemment, j'ai reçu une demande d'analyse d'image d'une personne qui fait des recherches sur les colloïdes, et je faisais diverses analyses tout en restant à la maison. Pour le moment, je viens de terminer un paragraphe, j'ai donc l'impression d'avoir résumé mon savoir-faire à partir d'images de cristaux colloïdaux qui roulaient sur le net.

En fait, les images obtenues lors des expériences sont souvent bruyantes et peuvent nécessiter un filtrage et un débruitage appropriés. À ce sujet, c'est essentiellement un jeu qui sort, ou une partie qui nécessite des essais et des erreurs. Je voudrais bientôt résumer les méthodes utiles. Ce sera un article compliqué.

Eh bien ~.

Recommended Posts

Vous pouvez le faire avec Python! Analyse structurale de cristaux colloïdaux bidimensionnels
Python | Ce que vous pouvez faire avec Python
Si vous écrivez TinderBot en Python, elle peut le faire
[Python] Que faites-vous avec la visualisation de 4 variables ou plus?
Vous pouvez l'essayer avec une copie! Dessinons un diagramme de réseau sympa avec networkx de Python
Ce que vous pouvez faire avec l'API vol.1
Analyse de conduction thermique bidimensionnelle non stationnaire avec Python
Ce que vous pouvez faire avec des compétences en programmation
Jusqu'à ce que vous puissiez utiliser opencv avec python
Vous devenez ingénieur en 100 jours - Jour 35 - Python - Ce que vous pouvez faire avec Python
Vous pouvez facilement créer une interface graphique même avec Python
Tu peux le voir! Comparaison des méthodes d'optimisation (2020)
Si vous les gars dans la cuisine de portée pouvez le faire avec une marge ~ ♪
Analyse statique du code Python avec GitLab CI
Analyse non linéaire géométrique du squelette élastique bidimensionnel avec Python
[Pour les débutants] Vous pouvez le faire à partir de zéro! Création d'API avec AWS SAM et sortie de documents Open API en Python
Prise en compte du moment où vous pouvez faire du bon travail en 10 ans avec Python3 et Scala3.
Jusqu'à ce que vous puissiez installer Blender et l'exécuter avec python pour le moment
[OpenCV / Python] J'ai essayé l'analyse d'image de cellules avec OpenCV
Calculer le coefficient de régression d'une analyse de régression simple avec python
Défiez l'analyse des composants principaux des données textuelles avec Python
Analyse du squelette de plan avec Python (4) Gestion du déplacement forcé
Ce que vous pouvez et ne pouvez pas faire avec Tensorflow 2.x
Jusqu'à ce que vous puissiez faire une reconnaissance d'image simple avec Jupyter
Combien connaissez-vous les bases de Python?
Analyse vocale par python
Faites Houdini avec Python3! !! !!
Analyse vocale par python
Analyse de données avec Python
Analyse de squelette planaire avec Python (3) Création d'un diagramme de force en coupe
Jusqu'à ce que vous puissiez installer votre propre bibliothèque Python avec pip
Effectuer une analyse isocurrent des canaux en eau libre avec Python et matplotlib
Faites Django avec CodeStar (Python3.6.8, Django2.2.9)
[Python] Analyse morphologique avec MeCab
[Analyse de co-occurrence] Analyse de co-occurrence facile avec Python! [Python]
Faites Django avec CodeStar (Python3.8, Django2.1.15)
Analyse des émotions par Python (word2vec)
Analyse statique des programmes Python
Analyse de squelette planaire avec Python
Analyse morphologique japonaise avec Python
Analyse des secousses musculaires avec Python
Activé pour convertir PNG en JPG avec Pillow of Python
Il semble que vous puissiez maintenant écrire des livres de portail avec blueqat
N'écrivez pas Python si vous voulez l'accélérer avec Python
Que faire si vous ne pouvez pas installer pyaudio avec pip #Python
Exercice pratique d'analyse de données avec Python ~ 2016 New Coder Survey Edition ~
Développement d'applications IOS avec Python (kivy) que même les singes peuvent faire
De l'introduction de JUMAN ++ à l'analyse morphologique du japonais avec Python
Matrice de similarité cosinus? Vous pouvez l'obtenir tout de suite avec NumPy