pepperumo/MVTec_Website
3
1import pandas as pd
2import plotly.graph_objects as go
3import streamlit as st
4from PIL import Image
5from joypy import joyplot
6import seaborn as sns
7import matplotlib.pyplot as plt
8
9# Function to load dataset
10def load_dataset():
11 file_path = "Data/mvtec_meta_features_dataset.csv"
12 try:
13 complete_df = pd.read_csv(file_path)
14
15 # Show available column names for debugging
16 print("Available columns:", complete_df.columns)
17
18 # Verify column presence
19 required_columns = ["category", "set_type", "anomaly_status"]
20 for col in required_columns:
21 if col not in complete_df.columns:
22 raise KeyError(f"Missing required column: {col}")
23
24 # Define the subclasses for each category
25 subclasses = {
26 'Texture-Based': ['carpet', 'wood', 'tile', 'leather', 'zipper'],
27 'Industrial Components': ['cable', 'transistor', 'screw', 'grid', 'metal_nut'],
28 'Consumer Products': ['bottle', 'capsule', 'toothbrush'],
29 'Edible': ['hazelnut', 'pill']
30 }
31
32 # Add a new column to the DataFrame to store the subclass
33 complete_df['subclass'] = complete_df['category'].apply(
34 lambda x: next((key for key, value in subclasses.items() if x in value), 'Unknown')
35 )
36
37 # Reorder columns to place 'subclass' after 'category'
38 cols = list(complete_df.columns)
39 cols.insert(cols.index('category') + 1, cols.pop(cols.index('subclass')))
40 complete_df = complete_df[cols]
41
42 return complete_df
43 except Exception as e:
44 st.error(f"Error loading dataset: {e}")
45 return None
46
47# Function to generate dataset statistics
48def dataset_statistics():
49 df = load_dataset()
50 if df is not None:
51 print("Loaded dataset preview:\n", df.head()) # Debugging step
52
53 # Aggregate counts for each category and condition
54 train_normal = df[(df['set_type'] == 'train') & (df['anomaly_status'] == 'normal')].groupby('category').size()
55 test_normal = df[(df['set_type'] == 'test') & (df['anomaly_status'] == 'normal')].groupby('category').size()
56 test_anomalous = df[(df['set_type'] == 'test') & (df['anomaly_status'] == 'anomalous')].groupby('category').size()
57
58 # Combine into a single DataFrame
59 final_summary = pd.DataFrame({
60 'Train Normal Images': train_normal,
61 'Test Normal Images': test_normal,
62 'Test Anomalous Images': test_anomalous
63 }).fillna(0).reset_index()
64
65 return final_summary
66 return None
67
68# Function to generate the bar chart
69def dataset_distribution_chart(df):
70 fig = go.Figure()
71
72 fig.add_trace(go.Bar(
73 x=df['category'],
74 y=df['Train Normal Images'],
75 name='Train Normal Images',
76 marker_color='blue'
77 ))
78 fig.add_trace(go.Bar(
79 x=df['category'],
80 y=df['Test Normal Images'],
81 name='Test Normal Images',
82 marker_color='red'
83 ))
84 fig.add_trace(go.Bar(
85 x=df['category'],
86 y=df['Test Anomalous Images'],
87 name='Test Anomalous Images',
88 marker_color='green'
89 ))
90
91 # Update layout
92 fig.update_layout(
93 title="Distribution of Normal and Anomalous Images per Category",
94 xaxis_title="Categories",
95 yaxis_title="Number of Images",
96 barmode='stack',
97 legend_title="Image Types"
98 )
99
100 # Display chart in Streamlit
101 st.plotly_chart(fig, use_container_width=True)
102
103# Function to display the complete dataframe with expander
104def display_dataframe():
105 df = load_dataset()
106 if df is not None:
107 with st.expander("Show Complete DataFrame"):
108 st.dataframe(df)
109
110
111
112def plot_bgr_pixel_densities(df, pixel_columns=['num_pixels_b', 'num_pixels_g', 'num_pixels_r']):
113 """
114 Generate JoyPy density plots for pixel counts of BGR channels for a given category.
115
116 Parameters:
117 df (pd.DataFrame): Filtered DataFrame for a single category.
118 pixel_columns (list): List of column names for BGR pixel counts.
119
120 Returns:
121 None
122 """
123 if df.empty:
124 st.warning("⚠️ No data available for the selected category.")
125 return
126
127 # Plot JoyPy density plot
128 fig, axes = joyplot(
129 data=df,
130 by="category", # Group by category
131 column=pixel_columns,
132 color=['blue', 'green', 'red'], # Colors for BGR channels
133 alpha=0.5,
134 fade=True,
135 legend=True,
136 linewidth=1.0,
137 overlap=3,
138 figsize=(8, 6) # Adjust the figure size here
139 )
140
141 # Add title and labels
142 plt.title(f'Density Plots for {df["category"].unique()[0]}', fontsize=14)
143 plt.xlabel('Number of Pixels Density', fontsize=12)
144 plt.ylabel('Categories', fontsize=12)
145
146 # Show the plot in Streamlit
147 st.pyplot(fig)
148
149
150def plot_pair_plots(complete_df):
151 """
152 Generate and display pair plots for each category in the dataset.
153
154 Parameters:
155 complete_df (pd.DataFrame): The input DataFrame containing image features and categories.
156
157 Returns:
158 None
159 """
160
161 # Define the features to be included in the pairplot
162 features = ['num_pixels_b', 'num_pixels_g', 'num_pixels_r', 'perceived_brightness']
163
164 # Create a separate pairplot for each category
165 for category in complete_df['category'].unique():
166 # Filter data for current category
167 category_df = complete_df[complete_df['category'] == category]
168
169 # Check if the filtered DataFrame is not empty
170 if not category_df.empty:
171 # Create PairGrid with hue and palette
172 g = sns.PairGrid(category_df, vars=features, hue='anomaly_status', palette={'normal': 'blue', 'anomalous': 'red'})
173
174 # Map the plots to the grid
175 g.map_upper(sns.scatterplot, alpha=0.6)
176 g.map_diag(sns.histplot, kde=True)
177 g.map_lower(sns.scatterplot, alpha=0.6)
178
179 # Add legend
180 g.add_legend()
181
182 # Customize the plot
183 g.figure.suptitle(f'Feature Relationships for {category.title()}', y=1.02, fontsize=14)
184
185 # Improve label readability
186 for i in range(len(g.axes)):
187 for j in range(len(g.axes)):
188 if g.axes[i][j] is not None:
189 g.axes[i][j].set_xlabel(g.axes[i][j].get_xlabel().replace('_', ' ').title())
190 g.axes[i][j].set_ylabel(g.axes[i][j].get_ylabel().replace('_', ' ').title())
191
192 # Adjust legend position to the right without overlapping the plots
193 g._legend.set_bbox_to_anchor((1.05, 0.5))
194 g._legend.set_loc('center left')
195
196 plt.tight_layout()
197 st.pyplot(g.figure)
198
199 