OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

OpenCV-drempel in Python met cv2.threshold()

Introductie

Thresholding is een eenvoudige en efficiënte techniek om elementaire segmentatie in een afbeelding uit te voeren en deze te binariseren (om te zetten in een binaire afbeelding) waarbij pixels ofwel 0 or 1 (of 255 als u gehele getallen gebruikt om ze weer te geven).

Meestal kunt u drempelwaarden gebruiken om eenvoudige achtergrond-voorgrondsegmentatie in een afbeelding uit te voeren, en het komt neer op varianten op een eenvoudige techniek voor elke pixel:

if pixel_value > threshold:
    pixel_value = MAX
else:
    pixel_value = 0

Dit essentiële proces staat bekend als: Binaire drempelwaarde. Nu - er zijn verschillende manieren waarop u dit algemene idee kunt aanpassen, inclusief het omkeren van de bewerkingen (omschakelen van de > teken met een < teken), het instellen van de pixel_value aan de threshold in plaats van een maximale waarde/0 (bekend als afkappen), waarbij de pixel_value zichzelf als het boven de is threshold of als het onder de . is threshold.

Al deze zijn handig geïmplementeerd in OpenCV als:

  • cv2.THRESH_BINARY
  • cv2.THRESH_BINARY_INV
  • cv2.THRESH_TRUNC
  • cv2.THRESH_TOZERO
  • cv2.THRESH_TOZERO_INV

… respectievelijk. Dit zijn relatief "naïeve" methoden in die zin dat ze vrij eenvoudig zijn, geen rekening houden met context in afbeeldingen, kennis hebben van welke vormen gebruikelijk zijn, enz. Voor deze eigenschappen zouden we veel meer rekenkundig duurder en krachtiger moeten gebruiken technieken.

Nu, zelfs met de "naïeve" methoden - sommige heuristieken kunnen worden toegepast om goede drempels te vinden, waaronder de Otsu-methode en de Triangle-methode:

  • cv2.THRESH_OTSU
  • cv2.THRESH_TRIANGLE

Opmerking: OpenCV-drempelwaarde is een rudimentaire techniek en is gevoelig voor lichtveranderingen en -gradiënten, kleurheterogeniteit, enz. Het kan het beste worden toegepast op relatief schone foto's, nadat ze zijn vervaagd om ruis te verminderen, zonder veel kleurvariatie in de objecten die u wilt segmenteren.

Een andere manier om enkele van de problemen met basisdrempels met een enkele drempelwaarde op te lossen, is door gebruik te maken van adaptieve drempelwaarde die een drempelwaarde toepast op elk klein gebied in een afbeelding, in plaats van globaal.

Eenvoudige drempelwaarde met OpenCV

Drempels in OpenCV's Python API wordt gedaan via de cv2.threshold() methode - die een afbeelding accepteert (NumPy-array, weergegeven met gehele getallen), de drempelwaarde, maximale waarde en drempelmethode (hoe de threshold en maximum_value worden gebruikt):

img = cv2.imread('objects.jpg')

img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)


blurred = cv2.GaussianBlur(img, (7, 7), 0)

ret, img_masked = cv2.threshold(blurred, 220, 255, cv2.THRESH_BINARY)

De retourcode is slechts de toegepaste drempel:

print(f"Threshold: {ret}") 

Hier, aangezien de drempel is 220 en we hebben de gebruikt THRESH_BINARY methode – elke pixelwaarde hierboven 220 zal worden verhoogd tot 255, terwijl elke pixelwaarde hieronder 220 wordt verlaagd tot 0, waardoor een zwart-witafbeelding wordt gemaakt, met een "masker", dat de objecten op de voorgrond bedekt.

Waarom 220? Als u weet hoe de afbeelding eruitziet, kunt u bij benadering raden welke drempel u kunt kiezen. In de praktijk zult u zelden een handmatige drempelwaarde willen instellen, en we zullen zo dadelijk de automatische drempelselectie behandelen.

Laten we het resultaat plotten! OpenCV-vensters kunnen een beetje kieskeurig zijn, dus we zullen de originele afbeelding, het wazige beeld en de resultaten plotten met Matplotlib:

fig, ax = plt.subplots(1, 3, figsize=(12, 8))
ax[0].imshow(img)
ax[1].imshow(blurred)
ax[2].imshow(img_masked)

Drempelmethoden

Zoals eerder vermeld, zijn er verschillende manieren waarop u de drempelwaarde en de maximale waarde in een functie kunt gebruiken. We hebben in eerste instantie de binaire drempel bekeken. Laten we een lijst met methoden maken en deze één voor één toepassen, waarbij we de resultaten plotten:

methods = [cv2.THRESH_BINARY, cv2.THRESH_BINARY_INV, cv2.THRESH_TRUNC, cv2.THRESH_TOZERO, cv2.THRESH_TOZERO_INV]
names = ['Binary Threshold', 'Inverse Binary Threshold', 'Truncated Threshold', 'To-Zero Threshold', 'Inverse To-Zero Threshold']

def thresh(img_path, method, index):
    img = cv2.imread(img_path)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    blurred = cv2.GaussianBlur(img, (7, 7), 0)
    ret, img_masked = cv2.threshold(blurred, 220, 255, method)

    fig, ax = plt.subplots(1, 3, figsize=(12, 4))
    fig.suptitle(names[index], fontsize=18)
    ax[0].imshow(img)
    ax[1].imshow(blurred)
    ax[2].imshow(img_masked)
    plt.tight_layout()

for index, method in enumerate(methods):
    thresh('coins.jpeg', method, index)

THRESH_BINARY en THRESH_BINARY_INV zijn inverse van elkaar, en binariseren een afbeelding tussen 0 en 255, door ze respectievelijk toe te wijzen aan de achtergrond en de voorgrond, en vice versa.

THRESH_TRUNC binariseert de afbeelding tussen threshold en 255.

THRESH_TOZERO en THRESH_TOZERO_INV binariseren tussen 0 en de huidige pixelwaarde (src(x, y)). Laten we eens kijken naar de resulterende afbeeldingen:

OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Bekijk onze praktische, praktische gids voor het leren van Git, met best-practices, door de industrie geaccepteerde normen en bijgevoegd spiekbriefje. Stop met Googlen op Git-commando's en eigenlijk leren het!

OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.
OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.
OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.
OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Deze methoden zijn intuïtief genoeg - maar hoe kunnen we een goede drempelwaarde automatiseren en wat betekent een 'goede drempelwaarde' eigenlijk? De meeste resultaten tot nu toe hadden niet-ideale maskers, met vlekken en vlekken erin. Dit komt door het verschil in de reflecterende oppervlakken van de munten - ze zijn niet uniform gekleurd vanwege het verschil in hoe ribbels licht reflecteren.

We kunnen dit tot op zekere hoogte bestrijden door een betere mondiale drempel te vinden.

Automatische/geoptimaliseerde drempels met OpenCV

OpenCV maakt gebruik van twee effectieve methoden voor het zoeken naar globale drempels: de methode van Otsu en de Triangle-methode.

Otsu's methode gaat ervan uit dat het werkt aan bi-modaal afbeeldingen. Bimodale afbeeldingen zijn afbeeldingen waarvan de kleurhistogrammen slechts twee pieken bevatten (dwz slechts twee verschillende pixelwaarden hebben). Aangezien de pieken elk tot een klasse behoren zoals een "achtergrond" en "voorgrond" - ligt de ideale drempel precies in het midden ervan.

OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.
Image credit: https://scipy-lectures.org/

Je kunt sommige afbeeldingen meer bimodaal maken met gaussiaanse vervaging, maar niet allemaal.

Een alternatief, vaak beter presterend algoritme is het driehoeksalgoritme, dat de afstand tussen het maximum en minimum van het grijswaardenhistogram berekent en een lijn trekt. Het punt waarop die lijn maximaal ver van de rest van het histogram verwijderd is, wordt als drempel gekozen:

OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Beide gaan uit van een grijsschaalafbeelding, dus we moeten de invoerafbeelding naar grijs converteren via cv2.cvtColor():

img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)

ret, mask1 = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU)
ret, mask2 = cv2.threshold(blurred, 0, 255, cv2.THRESH_TRIANGLE)

masked = cv2.bitwise_and(img, img, mask=mask1)

Laten we de afbeelding met beide methoden doornemen en de resultaten visualiseren:

methods = [cv2.THRESH_OTSU, cv2.THRESH_TRIANGLE]
names = ['Otsu Method', 'Triangle Method']

def thresh(img_path, method, index):
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (7, 7), 0)

    ret, img_masked = cv2.threshold(blurred, 0, 255, method)
    print(f"Threshold: {ret}")

    fig, ax = plt.subplots(1, 3, figsize=(12, 5))
    fig.suptitle(names[index], fontsize=18)
    ax[0].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    ax[1].imshow(cv2.cvtColor(gray, cv2.COLOR_BGR2RGB))
    ax[2].imshow(cv2.cvtColor(img_masked, cv2.COLOR_BGR2RGB))

for index, method in enumerate(methods):
    thresh('coins.jpeg', method, index)

OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.
OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Hier presteert de driehoeksmethode beter dan de methode van Otsu, omdat de afbeelding niet bimodaal is:

import numpy as np

img = cv2.imread('coins.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)

histogram_gray, bin_edges_gray = np.histogram(gray, bins=256, range=(0, 255))
histogram_blurred, bin_edges_blurred = np.histogram(blurred, bins=256, range=(0, 255))

fig, ax = plt.subplots(1, 2, figsize=(12, 4))

ax[0].plot(bin_edges_gray[0:-1], histogram_gray)
ax[1].plot(bin_edges_blurred[0:-1], histogram_blurred)

OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Het is echter duidelijk hoe de driehoeksmethode met de afbeelding kon werken en een bevredigender resultaat kon opleveren.

Beperkingen van OpenCV-drempels

Drempelen met OpenCV is eenvoudig, gemakkelijk en efficiënt. Toch is het vrij beperkt. Zodra je kleurrijke elementen, niet-uniforme achtergronden en veranderende lichtomstandigheden introduceert, wordt globale drempel als concept te rigide.

Afbeeldingen zijn meestal te complex om aan een enkele drempel te voldoen, en dit kan gedeeltelijk worden verholpen door: adaptieve drempelwaarde, waar veel lokale drempels worden toegepast in plaats van één globale. Hoewel ook beperkt, is adaptieve drempelwaarde veel flexibeler dan globale drempelwaarde.

Conclusie

In de afgelopen jaren zijn binaire segmentatie (zoals we hier deden) en multi-label segmentatie (waarbij je een willekeurig aantal klassen kunt coderen) met succes gemodelleerd met deep learning-netwerken, die veel krachtiger en flexibeler zijn. Bovendien kunnen ze globale en lokale context coderen in de afbeeldingen die ze segmenteren. Het nadeel is dat je data nodig hebt om ze te trainen, maar ook tijd en expertise.

Voor on-the-fly, eenvoudige drempelwaarden, kunt u OpenCV gebruiken. Voor nauwkeurige segmentatie op productieniveau wilt u neurale netwerken gebruiken.

Verder gaan - Praktisch diep leren voor computervisie

Je leergierige karakter maakt dat je verder wilt gaan? We raden aan om onze Type cursus: "Praktisch diep leren voor computervisie met Python".

OpenCV-drempelwaarde in Python met cv2.threshold() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Nog een cursus computervisie?

We zullen geen classificatie van MNIST-cijfers of MNIST-mode doen. Ze hebben lang geleden hun deel gediend. Te veel leermiddelen zijn gericht op basisgegevenssets en basisarchitecturen voordat geavanceerde black-box-architecturen de last van de prestaties op zich nemen.

We willen ons concentreren op demystificatie, uitvoerbaarheid, begrip, intuïtie en echte projecten. Willen leren hoe je kan een verschil maken? We nemen je mee op een reis van de manier waarop onze hersenen afbeeldingen verwerken tot het schrijven van een onderzoeksclassificatie voor diep leren voor borstkanker tot diepgaande leernetwerken die 'hallucineren', je de principes en theorie leren door middel van praktisch werk, en je uitrusten met de knowhow en tools om een ​​expert te worden in het toepassen van deep learning om computervisie op te lossen.

Wat zit erin?

  • De eerste principes van visie en hoe computers kunnen worden geleerd om te "zien"
  • Verschillende taken en toepassingen van computervisie
  • De tools van het vak die uw werk gemakkelijker maken
  • Datasets zoeken, maken en gebruiken voor computervisie
  • De theorie en toepassing van convolutionele neurale netwerken
  • Omgaan met domeinverschuiving, gelijktijdig voorkomen en andere vooroordelen in datasets
  • Overdragen Leren en de trainingstijd en computerbronnen van anderen gebruiken in uw voordeel
  • Het bouwen en trainen van een state-of-the-art classifier voor borstkanker
  • Hoe je een gezonde dosis scepsis toepast op mainstream ideeën en de implicaties begrijpt van algemeen aanvaarde technieken?
  • De "conceptruimte" van een ConvNet visualiseren met t-SNE en PCA
  • Casestudy's van hoe bedrijven computervisietechnieken gebruiken om betere resultaten te behalen
  • Correcte modelevaluatie, visualisatie van de latente ruimte en het identificeren van de aandacht van het model
  • Domeinonderzoek doen, eigen datasets verwerken en modeltesten opzetten
  • Geavanceerde architecturen, de voortgang van ideeën, wat ze uniek maakt en hoe ze te implementeren
  • KerasCV – een WIP-bibliotheek voor het maken van ultramoderne pijplijnen en modellen
  • Hoe papers te ontleden en te lezen en ze zelf te implementeren?
  • Modellen selecteren afhankelijk van uw toepassing
  • Een end-to-end machine learning-pijplijn maken
  • Landschap en intuïtie bij objectdetectie met snellere R-CNN's, RetinaNets, SSD's en YOLO
  • Instantie en semantische segmentatie
  • Realtime objectherkenning met YOLOv5
  • YOLOv5-objectdetectoren trainen
  • Werken met Transformers met KerasNLP (industriële WIP-bibliotheek)
  • Transformers integreren met ConvNets om bijschriften van afbeeldingen te genereren
  • DeepDream
  • Optimalisatie van Deep Learning-modellen voor computervisie

Tijdstempel:

Meer van Stapelmisbruik