CCINP Informatique Commune PC PSI 2023Sujet, corrigé et rapport du jury
Reconnaissance optique de caractères
- Programmation Python : listes, tableaux et dictionnaires
- Complexité et terminaison des algorithmes
- Représentation des nombres en binaire
- Dichotomie
- Graphes : flot maximal et coupe minimale
- Bases de données : requêtes SQL, jointures, agrégation
- Algorithmes de tri
- Apprentissage : K plus proches voisins
Téléchargements
Présentation du sujet
Reconnaissance optique de caractères : traitement d'image, flot maximal, SQL et K plus proches voisinsAfficher ou masquer la section
Présentation du sujet
Le sujet suit les étapes de la numérisation d'un document jusqu'à la reconnaissance de ses caractères. Il traite d'abord l'acquisition de l'image (niveaux de gris, binarisation), puis la rotation automatique, la détection des lignes et la restauration d'une image bruitée par un algorithme de flot maximal sur un graphe. Il se termine par l'interrogation d'une base de données de caractères en SQL et une classification par la méthode des K plus proches voisins.
- 1Partie I : acquisition d'un documentCodage binaire des couleurs, taille d'une image, complexité d'une conversion en niveaux de gris et binarisation.
- 2Partie II : reconnaissance du documentRotation par interpolation bilinéaire, segmentation en lignes, recherche de l'angle par dichotomie et restauration d'image par flot maximal (algorithme d'Edmonds-Karp).
- 3Partie III : détermination des caractèresRequêtes SQL sur une base de fontes, dictionnaires Python, calcul de distances, tri et méthode des K plus proches voisins.
L'épreuve en chiffres
Moyenne 9,97 / 20 · écart-type 3,88 · 4 216 présents · où vous situez-vous ?Afficher ou masquer la section
L'épreuve en chiffres
- Moyenne
- 9,97/ 20
- Écart-type
- 3,88
- Présents
- 4 216
- Coefficient
- 6
- Durée
- 3 h
Votre note sur 20 à ce sujet, en conditions de concours.
Source : document officiel du concours, épreuve du 26 avril 2023. Notes publiées par le concours (après harmonisation le cas échéant). Courbe : estimation par une loi normale.
Ce qu'a observé le jury
6 erreurs relevéesComplexité annoncée sans justification · Entiers non signés sur 8 bits mal compris · Terminaison de la dichotomie mal argumentéeAfficher ou masquer la section
Ce qu'a observé le jury
6 erreurs relevéesLe sujet couvrait une large part du nouveau programme d'informatique. Le document réponse a été globalement bien utilisé et les copies étaient plus propres que les années précédentes. Les questions de SQL ont permis à beaucoup de candidats de se relancer, tandis que la partie sur les graphes a été peu abordée.
Les erreurs les plus sanctionnées
- 1Complexité annoncée sans justificationQ2
Écrire O(n²) parce qu'il y a deux boucles ne suffit pas : il faut dire ce que représente n et préciser que le corps de boucle s'exécute en temps constant.
« beaucoup de candidats se contentent de dire "double boucle »
- 2Entiers non signés sur 8 bits mal comprisQ6
Un calcul négatif stocké sur 8 bits non signés donne un nombre positif qui n'est pas la valeur absolue, d'où un niveau de gris faux.
« un nombre négatif ne peut pas être représenté avec un nombre non signé »
- 3Terminaison de la dichotomie mal argumentéeQ9, Q10
La méthode est bien nommée, mais l'arrêt doit être justifié par la diminution de l'intervalle ; le calcul du milieu est aussi souvent faux.
« l'algorithme s'arrête car il y a un while avec un epsilon" n'est pas une réponse ! »
- 4Code fourni par l'énoncé non exploitéQ5, Q8
La gestion d'un drapeau pour repérer le début d'un bloc a dérouté ; le jury rappelle que comprendre un code écrit par d'autres est un objectif de formation.
« chercher à comprendre et à s'adapter à des codes écrits par d'autres fait aussi partie des objectifs de la formation »
- 5Dictionnaires mal initialisésQ20
Un append sur une clé absente provoque une erreur : il faut d'abord créer la liste associée à la clé.
« Très très peu de candidats pensent à initialiser le dictionnaire si la clé n'est pas présente »
- 6Erreurs de syntaxe SQL et PythonQ16 à Q18
En SQL : attribut.TABLE au lieu de TABLE.attribut, WHERE placé après GROUP BY, jointures sur de mauvais identifiants. En Python : parenthèses oubliées et appels du type L.append(a,b).
« d**1/2 est différent de d**(1/2) »
Ce qui a été bien réussi
- Les fonctions de binarisation et de choix de l'interpolation (Q3, Q4) et l'histogramme des lignes (Q7) sont bien traités.
- Les requêtes SQL (Q16 à Q18) sont assez bien réussies.
- La fonction distance (Q21) est souvent bien écrite.
- Une très grande partie des candidats analyse correctement les résultats finaux (Q27).
Conseils du jury
- Choisir des noms de variables explicites et soigner l'indentation, dont certaines erreurs rendent l'algorithme faux.
- Commenter le code avec mesure : trop de commentaires fait perdre un temps précieux.
- Préparer sa réponse au brouillon avant de la reporter proprement sur le document réponse, notamment pour les graphes.
- Connaître le nom et la complexité d'un tri naïf et d'un tri performant.
- Préciser le type des valeurs renvoyées par une fonction.
Synthèse rédigée par WikiPrépa à partir du rapport officiel du jury (à télécharger en PDF). Les citations sont extraites du rapport.
Ces sujets peuvent vous intéresser
Lecture du sujet en ligne
L'énoncé complet, avec les formules et les figures, sans ouvrir le PDF.Afficher ou masquer la section
Lecture du sujet en ligne
INFORMATIQUE
N.B. : le candidat attachera la plus grande importance à la clarté, à la précision et à la concision de la rédaction. Si un candidat est amené à repérer ce qui peut lui sembler être une erreur d'énoncé, il le signalera sur sa copie et devra poursuivre sa composition en expliquant les raisons des initiatives qu'il a été amené à prendre.
RAPPEL DES CONSIGNES
- Utiliser uniquement un stylo noir ou bleu foncé non effaçable pour la rédaction de votre composition ; d'autres couleurs, excepté le vert, peuvent être utilisées, mais exclusivement pour les schémas et la mise en évidence des résultats.
- Ne pas utiliser de correcteur.
- Écrire le mot FIN à la fin de votre composition.
Les calculatrices sont interdites.
Les différents algorithmes doivent être rendus dans leur forme définitive sur le Document Réponse dans l'espace réservé à cet effet en respectant les éléments de syntaxe du langage (les brouillons ne sont pas acceptés).
La réponse ne doit pas se limiter à la rédaction de l'algorithme sans explication, les programmes doivent être expliqués et commentés.
Document Réponse (DR) : 12 pages
Reconnaissance optique de caractères
Introduction
- acquisition d'un document et pré-traitement dans le but d'obtenir une image numérique pertinente;
- reconnaissance du contenu qui correspond à l'extraction du texte et de sa structure;
- reconnaissance des caractères par identification à l'aide d'une base de données.
Partie I - Acquisition d'un document
Une image en couleurs est stockée dans une matrice imgC de
Q1. Chaque entier représentant une couleur est représenté, en binaire, sous la forme d'un mot constitué de bits 0 et de 1 . Donner la taille de ce mot pour qu'il puisse représenter tous les entiers compris entre 0 et 255 . Indiquer les dimensions (en pixels) d'une image en couleurs au format A4 (
L'image en niveau de gris est une matrice imgg à
La formule utilisée pour déterminer la valeur d'un pixel gris en fonction des trois couleurs d'un pixel (R rouge, G vert, B bleu) est la suivante : pixGris
De manière générale, on nomme le type array pour représenter une matrice sous la forme d'une liste de listes dont les éléments de la liste interne pourront être des triplets pour les images en couleurs ou des entiers pour les images en niveau de gris.
On introduit les fonctions :
- dimension (img: array) -> tuple qui renvoie le triplet (
p, q, 3 ) pour une image en couleurs et le triplet (p, q, 1 ) pour une image en niveau de gris; - initialise(p:int, q:int, valeur:int) -> array qui renvoie une image de dimensions (
p, q ) où tous les pixels sont initialisés à une même valeur valeur.
def conversion_gris(imgC:array)->array:
n0,n1,_ = dimension(imgC)
img = initialise(p,q,0)
for i in range(n0):
for j in range(n1):
r,g,b = imgC[i][j]
val = 0.299 *r + 0.587 * g + 0.114 * b
img[i,j] = int(val)
return img
La première étape du prétraitement est la binarisation. Cela consiste à remplacer les pixels en niveaux de gris par des pixels noirs (valeur 0 ) ou blanc (valeur 255 ) uniquement. Pour cela, la valeur du pixel gris est comparée à une valeur seuil notée seuil.
Q3. Proposer une fonction binarisation(imgG:array, seuil:int)->array qui convertit une image en niveau de gris en image en noir et blanc en imposant une valeur 255 pour tout pixel de valeur strictement supérieure au seuil.
La difficulté de cette technique de binarisation est le choix de la valeur seuil pour des images ayant des problèmes d'éclairage. Nous verrons que la technique de restauration étudiée par la suite peut être utilisée pour remplacer la binarisation par seuil standard.
Partie II - Reconnaissance du document
II. 1 - Rotation de l'image

Beauté, limpidité, pureté, sérénité...

- en prenant les deux pixels voisins de la première ligne, à trouver la valeur du niveau de gris du pixel virtuel en supposant une évolution linéaire selon la coordonnée
y entre le pixel de gauche et le pixel de droite; - à faire de même en prenant les pixels de la deuxième ligne;
- enfin en travaillant sur la coordonnée
x , à supposer une évolution linéaire entre les deux valeurs trouvées aux deux étapes précédentes.
lineaire(x:float, x0:int, x1:int, pix0:int, pix1:int)-> float
qui renvoie le flottant val, approximation linéaire au point
Si les coordonnées du point virtuel
Q4. Choisir la fonction bilineaire(im:array,
Q5. Compléter la fonction rotation(im:array, angle:float)->array donnée dans le DR qui prend en argument une image en niveau de gris et un angle en degré et qui renvoie une nouvelle image tournée de l'angle angle donné en degré. On veillera à initialiser l'image par une image complètement blanche (pixels de valeur 255). On suppose définie une fonction :
prod_matrice_vecteur(M: array, v: list) -> list qui renvoie le vecteur colonne (sous forme de liste) résultat de la multiplication de la matrice M par le vecteur colonne v .
def lineaire(x:float, x0:int, x1:int, pix0:int, pix1:int)-> float:
return (x-x0)*(pix1-pix0)/(x1-x0) + pix0
Q6. Donner une raison pour laquelle il serait intéressant de se contraindre à 8 bits et expliquer le gain qu'il pourrait en découler en pratique.
Expliquer quel problème pourrait apparaître en réfléchissant au résultat de la soustraction 18 - 23 où 18 et 23 sont tous deux des entiers non signés sur 8 bits et où le résultat est lui aussi obligatoirement un entier non signé sur 8 bits.
En utilisant une telle structure (où pix0 et pix1 sont des entiers de type uint8), on se retrouve avec l'image pixellisée de la figure 5, ce qui n'est effectivement pas un résultat voulu, l'image attendue étant donnée sur la figure 6. L'angle choisi pour cette rotation n'est pas la valeur optimale assurant l'horizontalité du texte.
.jpg)

II. 2 - Segmentation
On peut ensuite détecter les lignes en sélectionnant les zones où il y a majoritairement des pixels blancs, ce qui correspond aux zones sans texte.
On applique ensuite le même principe pour détecter les mots et les lettres en comptant les pixels blancs verticalement.
On travaille sur une image binarisée, c'est-à-dire ne contenant que des pixels blancs (255) ou des pixels noirs (0).
Q7. Proposer une fonction histo_lignes(im:array)->list qui prend en argument une image binarisée et renvoie une liste contenant le nombre de pixels noirs de chaque ligne sans utiliser la fonction count.
La fonction appliquée au texte précédent, après rotation, renvoie la liste présentée sous forme d'un histogramme sur la figure 7.

Q8. Compléter sur le DR la fonction detecter_lignes(liste:list)->list prenant en argument une liste contenant le nombre de pixels noirs par ligne de l'image et qui renvoie une liste de couples (début ligne, fin ligne).
Cette fonction appliquée à notre exemple renvoie : [ [8, 36] , [38, 64] , [73, 102], [102, 132], [134, 160], [167, 193], [198, 227], [232, 257], [262, 291], [293, 322], [322, 351], [361, 382]].

L'algorithme peut être décrit de la manière suivante :
- partant d'un intervalle de départ
[a, b] avec les anglesa etb , on calcule : - le nombre de 0 de la liste fournie par la fonction histo_ligne pour les deux orientations
a etb , - le nombre de 0 de la liste fournie par la fonction histo_ligne pour l'orientation du milieu, noté
c = (a + b)/2 ; - on itère tant que l'intervalle de recherche
[a, b] est plus grand qu'un epsilon donné : - on calcule le nombre de 0 pour l'orientation au milieu, noté
ac , de l'intervalle[a, c] , - on calcule le nombre de 0 pour l'orientation au milieu, noté
cb , de l'intervalle[c, b] , - on cherche où se situe le maximum entre
ac, c oucb , - on en déduit le nouvel intervalle de recherche, comme étant celui entourant le maximum. Par exemple, si le maximum est en
c , alors le nouvel intervalle sera[ac, cb] .
Donner le nom de la méthode utilisée pour réaliser cet algorithme et préciser en justifiant le nombre d'itérations nécessaires pour obtenir la solution avec une précision notée

II. 3 - Restauration d'image
La méthode du flot maximal (ou méthode de la coupe minimale) reposant sur la représentation par un graphe de l'image à restaurer est souvent utilisée pour pallier ces problèmes.
La librairie maxflow disponible sous Python propose des fonctions déjà existantes pour traiter une image bruitée.
La fonction globale de traitement de l'image est la suivante :
import numpy
import maxflow
def graph_cut(img:array)->array:
img = numpy.array(img) #Conversion en array de Numpy pour un usage
plus facile ensuite
g = maxflow.Graph[int]() #création du graphe
nodeids = g.add_grid_nodes(dimension(img))
g.add_grid_edges(nodeids, 5)
g.add_grid_tedges(nodeids, img, 255-img)
g.maxflow()
sgm = g.get_grid_segments(nodeids)
img2 = numpy.int_(numpy.logical_not(sgm))
return img2
.jpg)
[ [ 0, 210, 190 ],
[ 20, 100, 200 ],
[ 10, 5, 255 ] ]
Les arêtes reliant deux sommets sont ensuite construites à l'aide de l'instruction g.add_grid_edges(nodeids, 5) entre un sommet et ses potentiels 4 voisins adjacents. À chaque arête
Q11. Représenter le graphe correspondant à l'image de (
Le flot est une notion similaire à un flux de fluide qui s'écoulerait de la source vers le puits. Mathématiquement, le flot est une fonction
-
∀e = (p, q) ∈ E (avecp, q deux sommets),f(p, q) = − f(q, p ), le flot dans le sensq versp est l'opposé du flot dans le sensp versq ; - pour tout sommet
p autre queS etP : ∑_(e = (p,) ∈ E)f(e) = 0 , la somme des flots arrivant et sortant d'un sommet est nulle, ce qui est similaire à la loi de Kirchoff; - pour toute arête
e ∈ E, f(e) ≤ w(e) , le flot ne peut pas dépasser la capacité maximale définie initialement.
On pourrait définir une matrice de flots similaire à la matrice de capacités qui contiendrait les valeurs des flots au lieu des capacités.
On passe du graphe non orienté que nous venons de décrire à un graphe orienté. Les arêtes faisant intervenir la source sont alors orientées de la source vers les sommets (flot sortant de la source); celles faisant intervenir le puits sont orientées des sommets vers le puits (flot entrant dans le puits); les arêtes entre des sommetsi etj correspondant à des pixels sont dédoublées (une dei versj , l'autre dej versi ) et ont chacune une capacité maximale égale à 5 . La figure 11 montre un exemple de flot sur une partie seulement du graphe de l'exemple étudié. Les étiquettes de la formei/j représentent pouri la valeur du flot et pourj la valeur de la capacité maximale.
Le flot est maximal lorsque les flots partant de la sourceS sont maximaux tout en respectant toutes les règles précédentes. On dit qu'une arête est saturée lorsque le flot de cette arête est égal à sa capacité.

.jpg)
L'algorithme de recherche du flot maximal est le suivant en pseudo-code :
Initialisation:
poser f(e) = 0 pour toute arête e
définir le graphe résiduel initial
définir un chemin C de S à P dans le graphe résiduel de longueur minimale
tant qu'il existe un chemin C de S à P dans le graphe résiduel faire
prendre un chemin C de longueur minimale
a = min(r(e)| e dans C)
pour tout e dans C faire
f(e) = f(e) + a
fin pour
mettre à jour le graphe résiduel
fin tant que
La capacité de la coupe est la somme des capacités des arcs orientés de A vers B. Par exemple, supposons que nous ayons coupé le graphe entre les ensembles

Pour réaliser cette coupe, on met dans l'ensemble A la source
L’appel g.get_grid_segments(nodeids) renvoie une liste indiquant, pour chacun des sommets, s'il appartient ou non au même ensemble que la source.
Q14. Dans l'exemple précédent, indiquer les deux ensembles
.jpg)
Partie III - Détermination des caractères
Le principe de cette méthode consiste à comparer chaque caractère à un ensemble de caractères définis dans une base de données.
III. 1 - Analyse de la base de données de caractères

- id : identifiant d'un symbole (entier), clé primaire;
- label : nom du symbole ("A", "a", "1", "é", "!" ...) (chaîne de caractères);
- catégorie : parmi majuscule, minuscule, chiffre, spécial (dont accent) (chaîne de caractères).
La table CARACTERES contient les attributs suivants : - id : identifiant d'un caractère (entier), clé primaire;
- id_symbole : identifiant du nom du symbole (entier);
- id_fonte : identifiant du type de fonte (entier);
- fichier : nom du fichier image correspondant (chaîne de caractères).
- id : identifiant d'une fonte (entier), clé primaire;
- nom : nom de la fonte ("Arial", "Times new roman", "Calibri", "Zurich", ...) (chaîne de caractères);
- famille : nom de la famille dont fait partie la fonte ("humane", "garalde", "réale", "didone", "scripte", ...) (chaîne de caractères);
- taille : dimension en hauteur des caractères en pixels (entier);
- graisse : type de graisse ("léger", "normal", "gras", "noir", ...) (chaîne de caractères);
- style : type de style ("romain", "italique", "ombré", "décoratif", ...) (chaîne de caractères).
Q16. Écrire une requête SQL permettant d'extraire les identifiants des fontes dont le nom est "Zurich", de style "romain" et dont la taille est comprise entre 10 et 16 pixels.
Q17. Écrire une requête SQL permettant d'extraire tous les noms de fichiers des caractères qui correspondent au symbole de label "A".
Q18. Écrire une requête SQL permettant d'indiquer le nombre de caractères correspondant à la fonte "Zurich", de style "romain" et dont la taille est comprise entre 10 et 16 pixels groupés selon les labels des symboles.
III. 2 - Classification automatique des caractères
nomFonte + "" + nomCatégorie+taillePolice + "" + idSymbole + ".png"
Les catégories sont définies par la liste :
categories = ["majuscules","minuscules","chiffres","special"].
Les symboles considérés sont définis par la liste :
symboles = ["ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz", "0123456789",".:, ; ' (!?) éèàçùêûâ"]. On compte 79 symboles différents.
Exemple : Zurich Light BT_majuscules18_10.png pour la majuscule K de la police Zurich Light BT en taille 18.
On introduit la fonction suivante :
def lire_symbole_fichier(nomFichier:str)->str:
car = nomFichier.split('_')
num = car[2].split('.')[0]
var = car[1][:Ien(car[1])-2]
ind = categories.index(var)
return symboles[ind][int(num)]
Q19. Indiquer ce que valent les variables car, num, var, ind et ce qui est renvoyé par la fonction si nomFichier="Zurich Light BT_majuscules18_10.png".
La commande img=imread(nomFichier) permet de lire le fichier image nomFichier et de stocker le tableau array à deux dimensions qui représente l'image dans la variable img.
Q20. Écrire une fonction lire_donnees_ref(fichiers_car_ref:list)->dict qui prend en argument la liste des noms de fichiers images fichiers_car_ref et qui renvoie le dictionnaire contenant tous les tableaux catégorisés.
La méthode d'identification utilisée est celle des K plus proches voisins. Elle consiste à calculer une distance entre l'image du caractère à identifier et toutes les images de référence. En notant (
Les distances
Q21. Écrire une fonction distance(im1:array, im2: array)->float qui calcule la distance entre les deux images im1 et im2 supposées de même dimension.
La suite consiste à déterminer les K plus petites distances et extraire les clés correspondantes, puis parmi ces clés déterminer la clé majoritaire. Une méthode envisageable est de trier les distances par ordre croissant pour prendre les
Q23. En se plaçant dans le pire des cas, indiquer le nom d'une méthode de tri performante envisageable, en précisant sa complexité temporelle en fonction de
Une méthode plus efficace est envisagée pour extraire directement les K plus petits éléments. Elle consiste à construire par tri par insertion la liste de taille K. L'algorithme correspondant est donné dans le
Q24. Compléter les 3 zones manquantes dans cet algorithme.
Q25. Préciser la complexité temporelle asymptotique dans le pire des cas de cet algorithme en fonction de
Q26. Écrire une fonction symbole_majoritaire(voisins:list)->str qui à partir de la liste voisins renvoyée par la fonction Kvoisins renvoie le symbole majoritaire.
| Nombre de voisins K | Type d'éléments dans la base de données | Nombre d'éléments dans la base
|
Caractères obtenus |
| 1 | fonte similaire au texte analysé | 79 images correspondant aux 79 symboles | "Bssi!-," |
| 4 | fonte similaire au texte analysé | 79 images correspondant aux 79 symboles | "Bssi!-," |
| 1 | 40 fontes proches de celle du texte analysé | 40*79 images correspondant aux 79 symboles | "Bsauté," |
| 4 | 40 fontes proches de celle du texte analysé | 40*79 images correspondant aux 79 symboles | "Bsauté," |
| 1 | 40 fontes pour 8 polices différentes | 320*79 images correspondant aux 79 symboles | "Beauté," |
| 4 | 40 fontes pour 8 polices différentes | 320*79 images correspondant aux 79 symboles | "Beauté," |
ANNEXE
Rappels des syntaxes en Python
| Fonctionnalités | Python | ||
| détermination du nombre de zéros dans la liste X | X.count(0) | ||
| définir une chaîne de caractères | mot = 'Python' | ||
| taille d'une chaîne | len(mot) | ||
| extraire des caractères (avec le même fonctionnement des indices que pour les extractions de souslistes) | mot [2:7] | ||
| éliminer le ln en fin d'une ligne | ligne.strip() | ||
|
mot.split(',') | ||
| ouverture d'un fichier en lecture et lecture des données (data est une liste de chaînes de caractères dont la taille est le nombre de lignes du fichier lu) | with open('nom_fichier','r') as f : data = f.readlines() |
FIN
![]() |
Nom :
|
|||||||||
| Prénom:
|
||||||||||
| Né(e) le |
|
|
|
|||||||
|
||||||||||
|
|
|||||||||
|
||||||||||
DOCUMENT RÉPONSE
Ce Document Réponse doit être rendu dans son intégralité.
| - | - | - | - | - | - | - | - | - | - | |
|
- | - |
|
- | lo | - | - | |
|
|||||||||||
|
|
- | - | - | - | - | - | - | - | - 0 - | - 7 - | 0 | ||||||||||||||||||
| - | - | 0.0 | - | 0.0 | - | - | - | ||||||||||||||||||||||
| - | - | ||||||||||||||||||||||||||||
| - | - | ||||||||||||||||||||||||||||
| - | |||||||||||||||||||||||||||||
| - | - 0.000 |
|
0.0 | - | 0.0 | - | - | ||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||
| - | |||||||||||||||||||||||||||||
| 0 | |||||||||||||||||||||||||||||
| Q | T | - | - | - | . | - | - | - | - | | | | | | | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | ||||
| - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
|
- | - | - | - | - | - | - | - | - | - | - | |||||||
| - | ![]() |
- | 䡤龧艃 | - | - | 龧龧龧 | - | - | - | - | ![]() |
- | |||||||||||||||||||||
| - | - | - | - | - | - | ![]() |
- | ||||||||||||||||||||||||||
|
|
![]() |
- | - | - | - | - | |||||||||||||||||||||||||||
| - | - | - | - | - | - |
|
|
- | - | - | . | . | - | - | - | - | - | - | ![]() |
- | ![]() |
![]() |
![]() |
![]() |
|||||||||
| - | - | lollowdent | - | - | - | - | - | - | - | 都龧龧龧 | - | d | - | - |
|
||||||||||||||||||
| - | - | - | - | - | - | - | 都 | - | ![]() |
- | , | - | - | - | ![]() |
||||||||||||||||||
|
|
- | + | - | - | - | ![]() |
- | ![]() |
| | ![]() |
![]() |
![]() |
![]() |
|
![]() |
![]() |
|
![]() |
|||||||||||||||
| - | - | | | ![]() |
- | - | - | |||||||||||||||||||||||||||
|
|
- | - | - | - | - | - | - | - | - | - | - | - | - | - | ![]() |
- | - | - | - | - | - | - | - |
|
|||||||||
| - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | ||||||||
|
|
- | - | -+ - |
|
- |
|
|||||||||||||||||||||||||||
|
|
- | - | ![]() |
- | - | - | ![]() |
- | - | ||||||||||||||||||||||||
|
|
- | - | - | - | - | - | - | - | - |
|
- | - | - | - | - | - | - | - | - | - | - | - | - | - | - | ||||||||
| - | - | - | - | d | - | ||||||||||||||||||||||||||||
| | | ![]() |
- | |||||||||||||||||||||||||||||||
![]() |
![]() |
- | ![]() |
![]() |
![]() |
![]() |
![]() |
- | - | ![]() |
![]() |
- | - | ![]() |
- | ![]() |
1 | ![]() |
![]() |
![]() |
1 | ![]() |
|||||||||||
def bilineaire(im:array,x:float,y:float)->int:
x0 = int(x)
x1 = x0+1
y0 = int(y)
y1 = y0+1
a = lineaire(y,y0,y1,im[x0][y0],im[x1][y1])
b = lineaire(y,y0,y1,im[x1][y0],im[x0][y1])
c = lineaire(x,x0,x1,a,b)
return int(c)
def bilineaire(im:array,x:float,y:float)->int:
x0 = int(x)
x1 = x0+1
y0 = int(y)
y1 = y0+1
a = lineaire(y,y0,y1,im[x0][y0],im[x0][y1])
b = lineaire(y,y0,y1,im[x1][y0],im[x1][y1])
c = lineaire(x,x0,x1,a,b)
return int(c)
x0 = int(x)
x1 = x0+1
y0 = int(y)
y1 = y0+1
a = lineaire(y,y0,y1,im[x0][y0],im[x0][y1])
b = lineaire(y,y0,y1,im[x0][y0],im[x1][y0])
c = lineaire(x,x0,y1,a,b)
return int(c)
def bilineaire(im:array,x:float,y:float)->int:
x0 = int(x)
x1 = x0+1
y0 = int(y)
y1 = y0+1
a = lineaire(y,y0,y1,im[x0][y0],im[x0][y1])
b = lineaire(y,y0,y1,im[x1][y0],im[x0][y1])
c = lineaire(y,y0,y1,a,b)
return int(c)
def rotation(im:array, angle:float)->array:
imr =
angr =
matR =
for ni in range (..........................):
for
if
return imr
def detecter_lignes(liste :list)->list :
lignes = []
i
deb = -1 #contient -1 tant qu'on parcourt des lignes de pixel blanc while
#début d'une suite de lignes contenant des pixels noirs if
deb =
#fin d'une suite de lignes contenant des pixels noirs
elif
......................
deb =
return lignes
| - |
|
- | ![]() |
![]() |
|
||||||||||||||||||||||||||||||
| - | - | - | - | - | - | - | - | ![]() |
|||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||
![]() |
|||||||||||||||||||||||||||||||||||
| - | - | ||||||||||||||||||||||||||||||||||
| - |
|
||||||||||||||||||||||||||||||||||
![]() |
|
||||||||||||||||||||||||||||||||||
| - | |||||||||||||||||||||||||||||||||||

Q10 - Fonction rotation_auto(im:array, a:float, b:float)->array
def nb_zeros(im :array, angle :float)->int:
imr = rotation(im, angle)
ligne = histo_ligne(imr)
f=ligne.count(0)
return f
fc = nb_zeros(im,c)
while
ac =
fac
cb =
fcb =
if ............. == maxi:
c = ac
fc = fac
elif ............. == maxi:
b = cb
else:
a =
c =
return rotation (im, (b+a)/2)
NE RIEN ÉCRIRE DANS CE CADRE
| S | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | P | |
| S | |||||||||||
| 1 | - | ||||||||||
| 2 | - | - | |||||||||
| 3 | - | - | - | ||||||||
| 4 | - | - | - | - | |||||||
| 5 | - | - | - | - | - | ||||||
| 6 | - | - | - | - | - | - | |||||
| 7 | - | - | - | - | - | - | - | ||||
| 8 | - | - | - | - | - | - | - | - | |||
| 9 | - | - | - | - | - | - | - | - | - | ||
| P | - | - | - | - | - | - | - | - | - | - |
.jpg)
.jpg)

.jpg)
car:
num :
Retour de la fonction :
var:
ind:
.jpg)
|
|
- | - | - | - | - | - | - | - | ![]() |
- | - | - | - | - | - | - | - | | |
|
- | - | | | | | | | - | T | | |
|
||||||
| - | - | - | - | - | - | - | - |
|
- | - | - | - | - | - | - | - | - | - | - | - | - | |||||||||||||
| - | ![]() |
![]() |
1 -llevellowlloge | |||||||||||||||||||||||||||||||
![]() |
||||||||||||||||||||||||||||||||||
![]() |
||||||||||||||||||||||||||||||||||
| Q21 | - | - | - | l | | | - | - | - |
|
- | - | - | | | - | - | | | - | - | | | | | |
|
|||||||||||||||||||||||||||||||||||||||
|
|
- | - | - | - | - | - | - | - | - | - | - | - | - | 0 | - |
|
||||||||||||||||||||||||||||||||||||||||||||
| - | - | ![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 7 - 7 - | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def Kvoisins(distances:dict,K:int)->list:
voisins = [(float("inf"),"") for k in range(K)]
for lettre in distances:
d = distances[lettre]
for j in range( ............. ):
if
k = len(voisins)-1
while
voisins[k] = voisins[k-1]
k = k - 1
voisins[k] = [d[j], lettre]
return voisins
Questions fréquentes
4 questionsSur quoi porte le sujet d'informatique CCINP PC PSI 2023 ?Afficher ou masquer la section
Questions fréquentes
4 questionsSur quoi porte le sujet d'informatique CCINP PC PSI 2023 ?
Sur la reconnaissance optique de caractères : traitement d'images en Python, dichotomie, flot maximal dans un graphe, requêtes SQL, dictionnaires, tris et méthode des K plus proches voisins.
Quelles erreurs le jury a-t-il relevées en informatique CCINP 2023 PC PSI ?
Des complexités non justifiées, une mauvaise compréhension des entiers non signés sur 8 bits, des dictionnaires non initialisés, des erreurs de syntaxe SQL (WHERE après GROUP BY) et des parenthèses oubliées en Python.
Le sujet d'informatique CCINP 2023 PC PSI contenait-il des erreurs ?
Oui : le programme donné en Q2 comportait des coquilles et le choix du chemin en Q13 était ambigu. Le jury indique avoir accepté les différentes interprétations cohérentes.
Comment gagner des points au SQL au CCINP informatique 2023 ?
Ces questions ont été assez bien réussies. Il faut écrire TABLE.attribut, placer WHERE avant GROUP BY, lier les bons identifiants dans les jointures et, au besoin, remplacer BETWEEN par une double comparaison.
Pas de description pour le moment


.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)

.jpg)
.jpg)

.jpg)
.jpg)
.jpg)
.jpg)
.jpg)

.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)