Jak vectorize obrazu pomocí opencv?

0

Otázka

Já používám termín "vectorize" protože to je to, co se používá k popisu procesu, o které píšu. Nevím, co je to vlastně jmenuje, ale to, co se snažím udělat, je vzít prvky obrazu a oddělit je do různých obrazů.

Zde je příklad obrázek snažím se "vectorize"

Co bych chtěl udělat, je (pomocí opencv) oddělit corncob ze zelené skladem to je připojen k, a jednotlivé corncob kus do své vlastní obrázky.

Co jsem zkoušel, jsou následující:

def kmeansSegmentation(path_to_images, image_name, path_to_save_segments):
    img = cv2.imread(path_to_images+image_name)

    img_blur = cv2.GaussianBlur(img, (3,3), 0)
    img_gray = cv2.cvtColor(img_blur, cv2.COLOR_BGR2GRAY)

    img_reshaped = img_gray.reshape((-1, 3))
    img_reshaped = np.float32(img_reshaped)
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)


    K = 5
    attempts = 10
    ret,label,center=cv2.kmeans(img_reshaped,K,None,criteria,attempts,cv2.KMEANS_PP_CENTERS)
    center = np.uint8(center)
    res = center[label.flatten()]

    v = np.median(res)
    sigma=0.33
    lower = int(max(0, (1.0 - sigma) * v))
    upper = int(min(255, (1.0 + sigma) * v))
    edges = cv2.Canny(img_gray, lower, upper)

    contours, hierarchy = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    sorted_contours= sorted(contours, key=cv2.contourArea, reverse= True)
    mask = np.zeros(img.shape[:2], dtype=img.dtype)



    array_of_contour_areas = [cv2.contourArea(contour) for contour in contours]
    contour_avg = sum(array_of_contour_areas)/len(array_of_contour_areas)
    contour_var = sum(pow(x-contour_avg,2) for x in array_of_contour_areas) / len(array_of_contour_areas)
    contour_std = math.sqrt(contour_var)


    print("Saving segments", len(sorted_contours))
    for (i,c) in tqdm(enumerate(sorted_contours)):
        if (cv2.contourArea(c) > contour_avg-contour_std*2):
            x,y,w,h= cv2.boundingRect(c)
            cropped_contour= img[y:y+h, x:x+w]
            cv2.drawContours(mask, [c], 0, (255), -1)
            #tmp_image_name= image_name + "-kmeans-" + str(K) + str(random.random()) + ".jpg"
            #cv2.imwrite(path_to_save_segments+tmp_image_name, cropped_contour)


    result = cv2.bitwise_and(img, img, mask=mask)
    
    """
    scale_percent = 30 # percent of original size
    width = int(edges.shape[1] * scale_percent / 100)
    height = int(edges.shape[0] * scale_percent / 100)
    dim = (width, height)


    resized = cv2.resize(result, dim, interpolation = cv2.INTER_AREA)

    cv2.imshow("edges", resized)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    """
    #tmp_image_name= image_name + "-kmeans-" + str(K) + str(random.random()) + ".png"
    #cv2.imwrite(path_to_save_segments+tmp_image_name, result)
    return result

Omluvte zakomentovaný kód, který mi stačí pozorovat změny, které jsem na obrázek, jak jsem změnit algoritmus.

opencv python
2021-11-23 02:57:28
1

Nejlepší odpověď

0

Věřím, že to, co se snažíte udělat, je něco, co nazývá "Stupně Segmentace". Tento proces se nejlépe provádí s hluboké techniky učení, které nemusí vyhovovat vám, pokud můžete najít pre-vyškoleni model. Tady je článek o tom, jak můžete udělat, že: https://www.analyticsvidhya.com/blog/2019/04/introduction-image-segmentation-techniques-python/

Více jednoduchý (ale méně přesné) řešení by mohlo být najít pomocí RGB prahové hodnoty pro vytvoření "osnovy" obrázek a pak použít flood fill algoritmu rozeznat konkrétní pixelů výsledného obrazu. Na hrubý obrys obrazu, budete muset experimentovat s různými prahovými hodnotami. Za prvé, převést celý obrázek do odstínů šedi w. OpenCV (cv2.imread('image-name', 0)). Testovat různé prahové hodnoty, jednoduše zkontrolujte, zda každý pixel hodnota je nad nebo pod určitou hodnotu (které si vyberete):

import numpy as np
import cv2
import matplotlib.pyplot as plt

def apply_threshold(img_array, threshold):
    threshold_applied = []
    for row in img_array:
        threshold_applied.append([])
        for pixel in row:
            if pixel>threshold:
                threshold_applied[len(threshold_applied)-1].append([255, 255, 255])
            else:
                threshold_applied[len(threshold_applied)-1].append([0, 0, 0])
    new_img = np.array(threshold_applied, np.uint8)
    cv2.imwrite(str(threshold)+".jpg", new_img)

img = cv2.imread("Ek1Dx.jpg", 0)
apply_threshold(img, 210)

Pokud spustit kód, můžete vidět, že výstup je velmi nepřesné a že klasu a zrna kukuřice jsou sotva viditelné. Například segmentace a dělení obrazů byl velmi velký problém počítačová věda za posledních deset let nebo tak. Mohou existovat i jiné filtry, které můžete použít k získat přesnější výsledky, ale myslím, že určení hranice je základní segmentace obrazu technika. Pokud chcete, můžete zkusit ladění s kolem mezní hodnoty v programu, aby zjistil, jestli to dostaneš více rozděleny obrázek.

2021-11-23 03:49:21

Díky za vaši odpověď. Můžete mi ukázat, jak to udělat druhá možnost, kterou jsi zmínil? Nemám dataset trénovat neuronovou síť s, který jsi zmínil v první možnost.
sololuvr

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................