铸钢缺陷检测的详细案例研究可以检测并分类钢中的缺陷

    科技2025-02-17  11

    In this blog post we will be talking and taking this problem which was in kaggle Competition a year ago ie., 2019.Here is the link to the competition: Click HereWe will solve this Case Study and try to be in top 5% or even less, by using very interesting techniques.

    在这篇博客文章中,我们将讨论和解决一年前在kaggle竞赛中出现的问题,即2019年。以下是竞赛的链接:单击此处,我们将解决此案例研究并尝试在5%以上或通过使用非常有趣的技术甚至更少。

    案例研究概述: (An Overview of the Case Study:)

    Problem Statement,

    问题陈述, Pipeline Thoughts,

    管道思想, Exploratory Data Analysis- EDA,

    探索性数据分析-EDA, Segmentation and its details,

    细分及其详细信息, Segmentation Models,

    细分模型 Training the Model,

    训练模型 Results,

    结果, Future Scope,

    未来范围 References and

    参考和 Contact

    联系 Lets go!

    我们走吧!

    1.问题陈述。 (1. Problem Statement.)

    概述: (Overview:)

    Steel is one of the most important building materials of modern times. Steel buildings are resistant to natural and man-made wear which has made the material ubiquitous around the world. To help make production of steel more efficient, this competition will help identify defects.And about the Company: Severstal is leading the charge in efficient steel mining and production. They believe the future of metallurgy requires development across the economic, ecological, and social aspects of the industry — and they take corporate responsibility seriously.

    钢铁是现代最重要的建筑材料之一。 钢结构建筑对自然和人为的磨损具有抵抗力,这使得这种材料在世界范围内无处不在。 为了帮助提高钢铁生产效率,本次比赛将有助于发现缺陷。 关于公司: 谢韦尔(Severstal )领导着高效钢的开采和生产。 他们认为,冶金的未来需要该行业的经济,生态和社会各方面的发展-他们认真对待企业责任。

    By the above given statements it is clear that we need to predict the location and type of defects found in steel manufacturing using the images provided. The images are named with a unique ImageId, and our task is to segment each image and classify the defects in the test set.

    通过以上给出的陈述,很明显,我们需要使用提供的图像来预测在钢铁制造中发现的缺陷的位置和类型 。 这些图像以唯一的ImageId命名,我们的任务是分割每个图像并对测试集中的缺陷进行分类。

    Each Image have 4 classes or 4 defects can be either No Defect(Ground Truth), or multiple classes with Id given (1,2,3,4)

    每个图像有4个类别或4个缺陷可以是No Defect(Ground Truth),也可以是具有ID(1,2,3,4)的多个类别

    I guess they are asking us to classify the defect and locate the segmentation of the defect of a given image, we will talk about segmentation in great details.

    我猜他们是在要求我们对缺陷进行分类并找到给定图像的缺陷分割,我们将详细讨论分割。

    Lets check if the given dataset have only 4 and not 5 defects, because it might cause problems, but that we will do in the EDA part :)

    让我们检查给定的数据集是否只有4个缺陷而不是5个缺陷,因为这可能会引起问题,但是我们将在EDA部分进行此操作:)

    2.管道策略 (2. Pipelines Strategies)

    This is Clearly a Multiclass Classification or can be a binary if there is just 1 defect in the image, we will use a Segmentation Model using Binary and Multi label Classifications.

    显然,这是一个多类分类,如果图像中只有1个缺陷,则可以是一个二元分类,我们将使用使用二值分类和多标签分类的细分模型。

    What is a Multi Label Classification?

    什么是多标签分类?

    Here is an Image, it can be a Single Classification task of finding or detecting Ironman(single_class) and Group of Avengers(multi_class).

    这是一张图片,它可以是查找或检测Ironman(单班)和复仇者组(multi_class)的单一分类任务。

    For any Multi label Image Classification model the first step is to get the data in a structured format, few of the things to remember is:

    对于任何多标签图像分类模型,第一步都是以结构化格式获取数据,要记住的几件事是:

    to have all the images in a folder on which we need to train the model,

    将所有图像放在我们需要训练模型的文件夹中, for training, we also need true labels of images so a .csv file which has all the names and their label.

    为了进行训练,我们还需要图像的真实标签,因此需要一个具有所有名称及其标签的.csv文件。 As a matter of fact we don’t need to create the .csv file from scratch as its already given in the Kaggle competition.

    事实上,我们不需要像在Kaggle竞赛中一样从头开始创建.csv文件。

    3.探索性数据分析 (3. Exploratory Data Analysis)

    Here is the Entire Code of the exploratory data analysis, if you are interested check it out and also I’ve explained in great details here below.

    这是探索性数据分析的整个代码,如果您有兴趣的话可以查看一下,下面我也对它进行了详细说明。

    #importing usefull library import pandas as pd import numpy as np import os import cv2 # visualization import matplotlib.pyplot as plt # plotly offline imports from plotly.offline import download_plotlyjs, init_notebook_mode, iplot from plotly import subplots import plotly.express as px import plotly.figure_factory as ff from plotly.graph_objs import * from plotly.graph_objs.layout import Margin, YAxis, XAxis # we use curlwget to import the data directly to the cloud # and install some packages below to extract them directly to the console of the colab !pip install pyunpack !pip install patool #above code to extract the files in the content path from pyunpack import Archive Archive('/content/train_images.zip').extractall('/content/train_images') #lets give a path just so that we dont need to enter everytime img_path = '/content/train_images/' train_df = pd.read_csv("/content/train.csv").fillna(-1) #Its give the information about train_df.info() # check the first image in the blog #Showing the 10 data from dataset csv file train_df.head(10) #Creting the dict with classId and Encoded pixcels and groupr all together #Creating the dict train_df['ClassId_EncodedPixels'] = train_df.apply(lambda row: (row['ClassId'], row['EncodedPixels']), axis = 1) #Groping together grouped_EncodedPixels = train_df.groupby('ImageId')['ClassId_EncodedPixels'].apply(list) print('No of unique Image: %s' % len(train_df['ImageId'].unique())) print('No of images having Minimum one defect: %s' % len(train_df[train_df['EncodedPixels'] != -1]['ImageId'].unique())) print('Total Traning sample: %s' % len(train_df[train_df['EncodedPixels'] != -1])) ''' this will print No of unique Image: 6666 No of images having Minimum one defect: 6666 Total Traning sample: 7095 ''' # picking up 10 examples for visualization examples = [] for r in grouped_EncodedPixels.iteritems(): if (len([x[1] for x in r[1] if x[1] != -1]) == 2) and (len(examples) < 10): examples.append(r[0]) def rle_to_mask(rle_string, height, width): ''' convert RLE(run length encoding) string to numpy array Parameters: rle_string (str): string of rle encoded mask height (int): height of the mask width (int): width of the mask Returns: numpy.array: numpy array of the mask ''' rows, cols = height, width if rle_string == -1: return np.zeros((height, width)) else: rle_numbers = [int(num_string) for num_string in rle_string.split(' ')] rle_pairs = np.array(rle_numbers).reshape(-1,2) img = np.zeros(rows*cols, dtype=np.uint8) for index, length in rle_pairs: index -= 1 img[index:index+length] = 255 img = img.reshape(cols,rows) img = img.T return img # visualize steel image with four classes of faults in seperate columns def viz_two_class_from_path(img_path, img_id, encoded_masks): ''' visualize an image with two types of defects by plotting them on two columns with the defect overlayed on top of the original image. Parameters: img_path (str): path of images img_id (str): image id or filename of the path encoded_masks (list): a list of strings of encoded masks Returns: matplotlib image plot in columns for two classes iwth defect ''' img = cv2.imread(os.path.join(img_path, img_id)) fig, ax = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(20,10)) cmaps = ["Reds", "Blues", "Greens", "Purples"] axid = 0 for idx, encoded_mask in enumerate(encoded_masks): class_id = idx + 1 if encoded_mask == -1: pass else: mask_decoded = rle_to_mask(encoded_mask, 256, 1600) ax[axid].get_xaxis().set_ticks([]) ax[axid].get_yaxis().set_ticks([]) ax[axid].text(0.25, 0.25, 'Image Id: %s - Class Id: %s' % (img_id, class_id), fontsize=20) ax[axid].imshow(img) ax[axid].imshow(mask_decoded, alpha=0.15, cmap=cmaps[idx]) axid += 1 # visualize the image we picked up earlier with mask for example in examples: img_id = examples mask_1, mask_2 = grouped_EncodedPixels[example] masks = [mask_1[1], mask_2[1]] viz_two_class_from_path('train_images/', example, masks # calculate sum of the pixels for the mask per class id train_df['mask_pixel_sum'] = train_df.apply(lambda x: rle_to_mask(x['EncodedPixels'], width=1600, height=256).sum(), axis=1) # calculate the number of pictures without any label what so ever annotation_count = grouped_EncodedPixels.apply(lambda x: 1 if len([1 for y in x if y[1]!= -1]) > 0 else 0).value_counts() annotation_count_labels = ['No Label' if x == 0 else 'Label' for x in annotation_count.index] # calculate number of defects per image defects_count_df = grouped_EncodedPixels.apply(lambda x: len([1 for y in x if y[1] != -1])) defect_count_per_image = defects_count_df.value_counts() defect_count_labels = defect_count_per_image.index trace0 = Bar(x=annotation_count_labels, y=annotation_count, name = 'Labeled vs Not Labeled') trace1 = Bar(x=defect_count_labels, y=defect_count_per_image, name = 'Defects Per Image') fig = subplots.make_subplots(rows=1, cols=2) fig.append_trace(trace0, 1, 1) fig.append_trace(trace1, 1, 2) fig['layout'].update(height=400, width=900, title='Defect Labels and Defect Frequency PerImage') plot(fig) # visualize steel image with four classes of faults in seperate columns def viz_one_class_from_path(img_path, img_id, mask, class_id, text=None): ''' visualize an image with two types of defects by plotting them on two columns with the defect overlayed on top of the original image. Parameters: img_path (str): path of images img_id (str): image id or filename of the path encoded_mask (str): RLE mask class_id (str): class id of the defect Returns: matplotlib image plot in columns for two classes with defect ''' img = cv2.imread(os.path.join(img_path, img_id)) mask_decoded = rle_to_mask(mask, 256, 1600) fig, ax = plt.subplots(figsize=(20,10)) cmaps = ["Reds", "Blues", "Greens", "Purples"] ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) if text: ax.text(0.25, 0.25, text, fontsize=24) ax.imshow(img) ax.imshow(mask_decoded, alpha=0.15, cmap=cmaps[int(class_id)-1]) def viz_per_class(train_df, class_id,text): class_samples = train_df[(train_df['ClassId']==class_id)&(train_df['EncodedPixels']!=-1)].sample(2) class_img_ids = class_samples['ImageId'].values class_encoded_masks = class_samples['EncodedPixels'].values for img_id, mask in zip(class_img_ids, class_encoded_masks): viz_one_class_from_path(img_path, img_id, mask, class_id,text=text) #we can now use the code to check each mask color of each class viz_per_class(train_df, 1,"Picture have Defect of class 1 and the mask colour is Red") #I've added all the images and executions in the medium blog, please check them out to ease out

    I’ve explained in my last blog on how to download gb’s of data in just minutes without having a high broad brand, here is the link of the blog, or you can follow the gist below.

    在上一个博客中,我已经解释了如何在短短几分钟内下载gb的数据而又没有很高的知名度,这是博客的链接,或者您可以按照以下要点进行操作。

    The Trick to download the data in a Snap: Step_1: Go to Google and type in CurlWget extension, and add it to your chrome or Firefox. Step_2: Check for the top right in your browser extension, it is now added to your chrome. Step_3: Now, for any download you make in our case its 9GB, just download the file like regularly BUT! cancel the download after 2 seconds. Step_4: Check for the Extension, you will see a huge text, when you scrool over the text, it say click to copy. Step_5: Just copy it, and open google colab where you are running the code and paste it after typing “!” and run the cell, example: !<paste_here> Step_6: Now it will take a few seconds or minutes to load it directly to your content of your google colab! Hurray!

    lets check the train.csv file given for us, here is what prints when you use the code from the gist given.

    让我们检查为我们提供的train.csv文件,这是使用给定要点的代码时打印的内容。

    train.csv contents train.csv内容

    we can check that we have a total No of unique Image: 6666,No of images having Minimum one defect: 6666,Total Training imagessample: 7095

    我们可以检查总共有唯一图像的数量:6666,具有最少一个缺陷的图像的数量:6666,总训练图像样本:7095

    At this point we have done our simple EDA, now you can see that we are using some function of rle_to_mask, so what is rle? it is run length encoding,

    至此,我们已经完成了简单的EDA,现在您可以看到我们正在使用rle_to_mask的某些功能,那么rle是什么? 它是游程长度编码,

    for example if you give input as wwwwaaadexxxxxx”, then the function should return “w4a3d1e1x6”.

    例如,如果输入为wwwwaaadexxxxxx”,则该函数应返回“ w4a3d1e1x6”。

    At this point we have made the funtion and before doing so we have grouped all the features and named it “grouped_EncodedPixels” if yoy followed the gist above.

    在这一点上,我们已经完成了功能,在此之前,如果您遵循上述要旨,则将所有功能分组并命名为“ grouped_EncodedPixels”。

    We tried to visualize some images from the path(images_path) and masked what we have found, here was the result of just class 1 and class 2 for simplicity :

    我们试图可视化来自path(images_path)的一些图像,并掩盖了我们发现的内容,为简单起见,这只是类1和类2的结果:

    Red for Class 1 and Blue for Class 2 1级为红色,2级为蓝色

    We have written the same function but for visualizing just 1 class of 4 each, here was the result:

    我们编写了相同的函数,但仅可视化了每个4类的1个类,结果如下:

    Visualizing one Class at a time 一次可视化一个类

    You can change the 1 from the function to 2 to view the class 2 defect, like here:

    您可以将1从函数更改为2以查看2类缺陷,如下所示:

    Visualizing one Class at a time 一次可视化一个类

    4.细分及其详细信息。 (4. Segmentation and its details.)

    What is segmentation? It is a process of giving a label to every pixel in a image, it takes a image and treats multiple objects of same class into one single entity, for example take a look:

    什么是细分? 这是给图像中的每个像素赋予标签的过程,它拍摄图像并将同一个类的多个对象视为一个实体,例如:

    Rough Example of Segmentation 细分示例

    To do this there are some of the most simplest and popular model architectures and we are going to use U-Net architecture, if you don’t know what U-net is its a U shaped architecture with different layers of Convolutions and pooling(very lame explanation from me sorry).

    为此,有一些最简单,最流行的模型架构,如果您不知道什么是U-net,它是具有不同卷积和池化层的U形架构,我们将使用U-Net架构。我的脚解释对不起)。

    5.细分模型 (5. Segmentation Models)

    There are many segmentation models but as we discussed we will using U-net to solve our problem and consider it as out First Cut Approach, so you might be wondering why U-net?

    细分模型很多,但是正如我们讨论的那样,我们将使用U-net解决问题并将其视为First Cut方法,因此您可能想知道为什么要使用U-net?

    The U-Net is an upgrade to the simple FCN architecture. It has skip connections from the output of convolution blocks to the corresponding input of the transposed-convolution block at the same level.

    U-Net是对简单FCN体系结构的升级。 它具有从卷积块的输出到相同级别的转置卷积块的相应输入的跳过连接。

    source) 来源 )

    This skip connections allows gradients to flow better and provides information from multiple scales of the image size. Information from larger scales (upper layers) can help the model classify better. Information from smaller scales (deeper layers) can help the model segment/localize better.

    这种跳过连接可以使渐变更好地流动,并提供来自多个图像尺寸比例的信息。 来自较大范围(上层)的信息可以帮助模型更好地分类。 来自较小尺度(较深层)的信息可以帮助模型更好地进行分段/定位。

    And its very easy to import and use, just use the following:

    它非常易于导入和使用,只需使用以下命令:

    from segmentation_models import Unet model = Unet('resnet34', input_shape=(128, 800, 3), classes=4, activation='sigmoid') if there is any error check this: https://github.com/qubvel/segmentation_models

    6.训练模型 (6. Training the Model)

    At this point I was thinking, why not take Encoded Pixels in slices and check how it performs, here is the code:

    在这一点上,我在想,为什么不对切片中的编码像素进行检查,并检查其性能,下面是代码:

    # Importing necessary libraries and csv data #ref: https://www.kaggle.com/jaysmit/u-net import numpy as np, pandas as pd, os, gc import matplotlib.pyplot as plt, time from PIL import Image import warnings warnings.filterwarnings("ignore") path = '../input/' train = pd.read_csv(path + 'train.csv') # RESTRUCTURE TRAIN DATAFRAME train['ImageId'] = train['ImageId_ClassId'].map(lambda x: x.split('.')[0]+'.jpg') train2 = pd.DataFrame({'ImageId':train['ImageId'][::4]}) train2['e1'] = train['EncodedPixels'][::4].values train2['e2'] = train['EncodedPixels'][1::4].values train2['e3'] = train['EncodedPixels'][2::4].values train2['e4'] = train['EncodedPixels'][3::4].values train2.reset_index(inplace=True,drop=True) train2.fillna('',inplace=True); train2['count'] = np.sum(train2.iloc[:,1:]!='',axis=1).values train2.head() The Result of the slices 切片结果

    We will now create a Class to take in Data and utilize it everytime we call it:

    现在,我们将创建一个类来接收数据,并在每次调用它时加以利用:

    class DataGenerator(keras.utils.Sequence): def __init__(self, df, batch_size = 16, subset="train", shuffle=False, preprocess=None, info={}): super().__init__() self.df = df self.shuffle = shuffle self.subset = subset self.batch_size = batch_size self.preprocess = preprocess self.info = info if self.subset == "train": self.data_path = path + 'train_images/' elif self.subset == "test": self.data_path = path + 'test_images/' self.on_epoch_end() def __len__(self): return int(np.floor(len(self.df) / self.batch_size)) def on_epoch_end(self): self.indexes = np.arange(len(self.df)) if self.shuffle == True: np.random.shuffle(self.indexes) def __getitem__(self, index): X = np.empty((self.batch_size,128,800,3),dtype=np.float32) y = np.empty((self.batch_size,128,800,4),dtype=np.int8) indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size] for i,f in enumerate(self.df['ImageId'].iloc[indexes]): self.info[index*self.batch_size+i]=f X[i,] = Image.open(self.data_path + f).resize((800,128)) if self.subset == 'train': for j in range(4): y[i,:,:,j] = rle2maskResize(self.df['e'+str(j+1)].iloc[indexes[i]]) if self.preprocess!=None: X = self.preprocess(X) if self.subset == 'train': return X, y else: return X

    Just like in the EDA part we had a rle_to_mask functions, lets create more which are needed:

    就像在EDA部分中一样,我们有一个rle_to_mask函数,让我们创建更多需要的函数:

    from keras import backend as K def rle2maskResize(rle): # CONVERT RLE TO MASK if (pd.isnull(rle))|(rle==''): return np.zeros((128,800) ,dtype=np.uint8) height= 256 width = 1600 mask= np.zeros( width*height ,dtype=np.uint8) array = np.asarray([int(x) for x in rle.split()]) starts = array[0::2]-1 lengths = array[1::2] for index, start in enumerate(starts): mask[int(start):int(start+lengths[index])] = 1 return mask.reshape( (height,width), order='F' )[::2,::2] def mask2contour(mask, width=3): w = mask.shape[1] h = mask.shape[0] mask2 = np.concatenate([mask[:,width:],np.zeros((h,width))],axis=1) mask2 = np.logical_xor(mask,mask2) mask3 = np.concatenate([mask[width:,:],np.zeros((width,w))],axis=0) mask3 = np.logical_xor(mask,mask3) return np.logical_or(mask2,mask3) Using TensorFlow backend. def mask2pad(mask, pad=2): w = mask.shape[1] h = mask.shape[0] for k in range(1,pad,2): temp = np.concatenate([mask[k:,:],np.zeros((k,w))],axis=0) mask = np.logical_or(mask,temp) for k in range(1,pad,2): temp = np.concatenate([np.zeros((k,w)),mask[:-k,:]],axis=0) mask = np.logical_or(mask,temp) for k in range(1,pad,2): temp = np.concatenate([mask[:,k:],np.zeros((h,k))],axis=1) mask = np.logical_or(mask,temp) for k in range(1,pad,2): temp = np.concatenate([np.zeros((h,k)),mask[:,:-k]],axis=1) mask = np.logical_or(mask,temp) return mask def dice_coef(y_true, y_pred, smooth=1): y_true_f = K.flatten(y_true) y_pred_f = K.flatten(y_pred) intersection = K.sum(y_true_f * y_pred_f) return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)

    And as you can check the last gist code line of function dice_coef(), its the evaluation we are checking as a loss function for this competition as it is a requirement and lets import the segmentation model of U-net.

    正如您可以检查函数dice_coef()的最后一个摘要代码行一样,我们正在评估此评估是否为该竞争的损失函数,因为这是一项要求,可以导入U-net的细分模型。

    ! pip install segmentation-models from segmentation_models import Unet from segmentation_models.backbones import get_preprocessing preprocess = get_preprocessing('resnet34') model = Unet('resnet34', input_shape=(128, 800, 3), classes=4, activation='sigmoid') model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[dice_coef]) # TRAIN AND VALIDATE MODEL idx = int(0.8*len(train2)); print() train_batches = DataGenerator(train2.iloc[:idx],shuffle=True,preprocess=preprocess) valid_batches = DataGenerator(train2.iloc[idx:],preprocess=preprocess) history = model.fit_generator(train_batches, validation_data = valid_batches, epochs = 30, verbose=2) Epoch 30 Result 纪元30结果

    Lets look at the plot:

    让我们看一下情节:

    plot of the model 模型图

    7.结果 (7. Results)

    We can observe that the at the 30th epoch the val_loss is a bit further then th train_loss, its okay for the First Cut, the model is able to capture what we are looking for in a nice manner, lets predict what the model captures.

    我们可以观察到,在第30个时间段,val_loss距train_loss略远,对于第一次切割来说还可以,该模型能够很好地捕获我们正在寻找的内容,让我们预测模型捕获的内容。

    # PREDICT FROM VALIDATION SET (ONLY IMAGES WITH DEFECTS) val_set = train2.iloc[idx:]; defects = list(val_set[val_set['e1']!=''].sample(6).index) defects += list(val_set[val_set['e2']!=''].sample(6).index) defects += list(val_set[val_set['e3']!=''].sample(14).index) defects += list(val_set[val_set['e4']!=''].sample(6).index) valid_batches = DataGenerator(val_set[val_set.index.isin(defects)],preprocess=preprocess) preds = model.predict_generator(valid_batches,verbose=1) # PLOT PREDICTIONS valid_batches = DataGenerator(val_set[val_set.index.isin(defects)]) print('Plotting predictions...') print('KEY: yellow=defect1, green=defect2, blue=defect3, magenta=defect4') for i,batch in enumerate(valid_batches): plt.figure(figsize=(20,36)) for k in range(16): plt.subplot(16,2,2*k+1) img = batch[0][k,] img = Image.fromarray(img.astype('uint8')) img = np.array(img) dft = 0 extra = ' has defect ' for j in range(4): msk = batch[1][k,:,:,j] if np.sum(msk)!=0: dft=j+1 extra += ' '+str(j+1) msk = mask2pad(msk,pad=2) msk = mask2contour(msk,width=3) if j==0: # yellow img[msk==1,0] = 235 img[msk==1,1] = 235 elif j==1: img[msk==1,1] = 210 # green elif j==2: img[msk==1,2] = 255 # blue elif j==3: # magenta img[msk==1,0] = 255 img[msk==1,2] = 255 if extra==' has defect ': extra ='' plt.title('Train '+train2.iloc[16*i+k,0]+extra) plt.axis('off') plt.imshow(img) plt.subplot(16,2,2*k+2) if dft!=0: msk = preds[16*i+k,:,:,dft-1] plt.imshow(msk) else: plt.imshow(np.zeros((128,800))) plt.axis('off') mx = np.round(np.max(msk),3) plt.title('Predict Defect '+str(dft)+' (max pixel = '+str(mx)+')') plt.subplots_adjust(wspace=0.05) plt.show() Prediction Result 预测结果

    These are some nice performance of the model and its predicting the defects well but its not predicting that well when there are 2 defects, we can work on it and can consider as future scope as I think this can be a nice First Cut Approach.

    这些是模型的良好性能,可以很好地预测缺陷,但是当存在2个缺陷时,不能很好地预测缺陷,我们可以对其进行研究,并可以考虑作为将来的范围,因为我认为这可能是一个很好的“初切方法”。

    8.未来范围 (8. Future Scope)

    I think if we add a better pipeline using tf.data from keras, we can get much more better results.

    我认为,如果使用来自keras的tf.data添加更好的管道,我们可以获得更好的结果。

    2. Use Data Augmentation techniques for both train and test data, might be helpful but its worth a try if necessary.

    2.将数据增强技术用于训练和测试数据,可能会有所帮助,但在必要时值得尝试。

    9.参考 (9. References)

    https://www.kaggle.com/c/severstal-steel-defect-detection/overview/evaluation

    https://www.kaggle.com/c/severstal-steel-defect-detection/overview/evaluation

    https://segmentation-models.readthedocs.io/en/latest/tutorial.html

    https://segmentation-models.readthedocs.io/en/latest/tutorial.html

    10.联系方式 (10. Contact)

    Link to my LinkedIn profile.

    链接到我的LinkedIn个人资料。

    11.经过几次曲折和错误后,我获得的Kaggle得分高居前1% (11. Kaggle Score which I got after some trail and error was in top 1%)

    Kaggle Private Score Kaggle私人分数

    I thank you for your view, hope you got someting from this blog, in the next blog we will talk more about the input pipeline using tf.data from keras, check out more articles from me here in medium.

    我感谢您的观点,希望您对此博客有所了解,在下一个博客中,我们将使用来自keras的tf.data讨论有关输入管道的更多信息,在中此查看我的更多文章。

    翻译自: https://medium.com/@saivenkat_/a-detailed-case-study-on-severstal-steel-defect-detection-can-we-detect-and-classify-defects-in-2844402392cc

    相关资源:阀门铸钢件外观检测国标
    Processed: 0.011, SQL: 8