Home > Enterprise >  How to solve the error UnboundLocalError: local variable 'max_contour' referenced before a
How to solve the error UnboundLocalError: local variable 'max_contour' referenced before a

Time:03-12

Hello everyone I hope you are doing well I have implemented the following code. Here is my dataset https://drive.google.com/drive/folders/1ARQLty-f7i_W6fvvcIx-3VUUzjb3o1KX?usp=sharing

I read the dicom files from the folder and apply some preprocessing to it to the segment area. I have developed a function that segment the area, but I am getting the following error where I got the following error when I run the code

How can I solve that

UnboundLocalError: local variable 'max_contour' referenced before assignment


from matplotlib.pyplot import imshow
import matplotlib.pyplot as plt
import pydicom
import numpy
import tkinter
from tkinter import filedialog
import os
import numpy as np
import pydicom as dcm
import cv2
def window_image(img, window_center,window_width, intercept, slope, rescale=True):
    img = (img*slope  intercept) #for translation adjustments given in the dicom file. 
    img_min = window_center - window_width//2 #minimum HU level
    img_max = window_center   window_width//2 #maximum HU level
    img[img<img_min] = img_min #set img_min for all HU levels less than minimum HU level
    img[img>img_max] = img_max #set img_max for all HU levels higher than maximum HU level
    if rescale: 
     img = (img - img_min) / (img_max - img_min)*255.0 
    return img

def preprocess_dicom(img,outdir,image_path):
    ht, wd = img.shape[:2]

    # convert to grayscale
    #gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    # threshold
    thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU)[1]

    # get external contours
    contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    #contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    
    max_aspect=0
    for cntr in contours:
        x,y,w,h = cv2.boundingRect(cntr)
        aspect = w/h
        if aspect > max_aspect:
            max_aspect = aspect
            max_contour = cntr
    
    # create mask from max_contour
    mask = np.zeros((ht,wd), dtype=np.uint8)
    mask = cv2.drawContours(mask, [max_contour], 0, (255), -1)

    # dilate mask
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
    mask = cv2.morphologyEx(mask, cv2.MORPH_DILATE, kernel)

    # invert mask
    mask = 255 - mask

    # mask out region in input
    result = img.copy()
    result = cv2.bitwise_and(result, result, mask=mask)

    # save resulting image
     # Open the outlined image
    fig, ax = plt.subplots(1,2)
    ax[0].imshow(img,'gray');
    ax[1].imshow(result,'gray');
    cv2.imwrite(os.path.join(outdir,os.path.basename(image_path).replace(".dcm", "_segment.png")), result)
    return result  

def get_first_of_dicom_field_as_int(x):
    #get x[0] as in int is x is a 'pydicom.multival.MultiValue', otherwise get int(x)
    if type(x) == dcm.multival.MultiValue: return int(x[0])
    else: return int(x)
    
def get_windowing(data):
    dicom_fields = [data[('0028','1050')].value, #window center
                    data[('0028','1051')].value, #window width
                    data[('0028','1052')].value, #intercept
                    data[('0028','1053')].value] #slope
    return [get_first_of_dicom_field_as_int(x) for x in dicom_fields]






root=tkinter.Tk()
root.withdraw()

currdir=os.getcwd()
PathDicom=filedialog.askdirectory(parent=root,initialdir=currdir,title='Please select a folder with DICOM')

if len (PathDicom)>0:
    print(("You chose %s")%PathDicom)
    
lstFilesDCM=[]
for dirName,subdirList,fileList in os.walk(PathDicom):
    for filename in fileList:
        if ".dcm" in filename.lower():
            lstFilesDCM.append(os.path.join(dirName,filename))
RefDs=pydicom.dcmread(lstFilesDCM[0])
ConstPixelDims=(int(RefDs.Rows),int(RefDs.Columns),len(lstFilesDCM))
cal=RefDs.RescaleIntercept
ArrayDicom=numpy.zeros(ConstPixelDims,dtype=RefDs.pixel_array.dtype)
ind = 0 
folder_name=r'C:\Users\Hammad\Desktop'
for i in lstFilesDCM:
    for j in range(1, len(lstFilesDCM)):
        ds=pydicom.dcmread(i)
        ArrayDicom[:,:,lstFilesDCM.index(i)]=ds.pixel_array
        
        window_center , window_width, intercept, slope = get_windowing(ds)
        output = window_image(ArrayDicom[:,:,j], window_center, window_width, intercept, slope)
        imshow(output,cmap='gray')
        output = output - np.min(output)
        output = output / np.max(output)
        output = (output * 255).astype(np.uint8)
        imgsegment=preprocess_dicom(output,r'C:\Users\Hammad\Desktop\manifest-1643119746471\manifest-1645243048125\CPTAC-SAR',i)
        RefDs.PixelData = imgsegment.tobytes()
        RefDs.save_as( folder_name  '/{0}.dcm'.format(ind))    
        ind = ind 1

Can anybody please help me in this

CodePudding user response:

max_contour seems to be getting defined first within the for loop, but you're using it outside the for loop (mask = cv2.drawContours(mask, [max_contour], 0, (255), -1)). Try defining max_contour near max_aspect, which is also accessible to the line with the mask.

max_aspect = 0
max_contour = 0

CodePudding user response:

for cntr in contours:
    x,y,w,h = cv2.boundingRect(cntr)
    aspect = w/h
    if aspect > max_aspect:
        max_aspect = aspect
        max_contour = cntr

This the only place in the code where max_contour is defined. So, if you're getting that error, it must mean that the line of code max_contour = cntr was never executed.

This would be caused by contours being empty, or aspect > max_aspect always being false.

  • Related