如何解决错误 UnboundLocalError: local variable 'max_contour'赋值前引用

发布于 2025-01-13 10:02:48 字数 4910 浏览 0 评论 0原文

Hello everyone I hope you are doing well I have implemented the following code. 这是我的数据集 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 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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

天涯离梦残月幽梦 2025-01-20 10:02:48
for cntr in contours:
    x,y,w,h = cv2.boundingRect(cntr)
    aspect = w/h
    if aspect > max_aspect:
        max_aspect = aspect
        max_contour = cntr

这是代码中定义 max_contour 的唯一位置。因此,如果您收到该错误,则一定意味着 max_contour = cntr 代码行从未执行过。

这可能是由于 contours 为空,或者 aspect > > 造成的。 max_aspect 始终为 false。

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.

孤云独去闲 2025-01-20 10:02:48

max_contour 似乎是在 for 循环中首先定义的,但是您在 for 循环之外使用它 (mask = cv2.drawContours(mask, [max_contour], 0, (255) ,-1))。尝试在 max_aspect 附近定义 max_contour,也可以通过带有遮罩的线访问。

max_aspect = 0
max_contour = 0

编辑:问题是,仅当且仅当轮廓列表中存在轮廓(变量contours)时才会更新max_contour。因此,max_contour 的默认值不会被 drawContours 接受,因为它期望一个非空轮廓(因此 (-215:Assertion failed) npoints > 0您遇到的错误)。

解决方案是仅在找到轮廓时才创建蒙版。如果没有,我们可以返回原始图像,因为没有可应用的掩模。

所以代码看起来像这样:

max_contour = []  # Let's initialize to a list instead of 0 since I think that would make more sense. This has no effect on the code itself.
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

if contours: # This checks if the list of contours is not empty. You could also do `if max_contour:` since that should be satisfied if `max_contour` is non-empty.
    # create mask from max_contour
    mask = np.zeros((ht,wd), dtype=np.uint8)
    ...   # The rest of the code until `return result`
    return result
else:
    return img   # return the original image if the list of contours is empty

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

Edit: The issue is that max_contour is only updated if and only if a contour exists in the list of contours (the variable contours). So the default value for max_contour will not be accepted by drawContours since it's expecting a non-empty contour (hence the (-215:Assertion failed) npoints > 0 error you encountered).

The solution would be to only create a mask if a contour is found. If not, we could return the original image since there's no mask to apply.

So the code would look something like this:

max_contour = []  # Let's initialize to a list instead of 0 since I think that would make more sense. This has no effect on the code itself.
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

if contours: # This checks if the list of contours is not empty. You could also do `if max_contour:` since that should be satisfied if `max_contour` is non-empty.
    # create mask from max_contour
    mask = np.zeros((ht,wd), dtype=np.uint8)
    ...   # The rest of the code until `return result`
    return result
else:
    return img   # return the original image if the list of contours is empty
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文