Spaces:
				
			
			
	
			
			
		Runtime error
		
	
	
	
			
			
	
	
	
	
		
		
		Runtime error
		
	Update app.py
Browse files
    	
        app.py
    CHANGED
    
    | @@ -1,113 +1,175 @@ | |
| 1 | 
            -
            import  | 
| 2 | 
             
            import torch
         | 
| 3 | 
            -
             | 
| 4 | 
             
            import numpy as np
         | 
| 5 | 
            -
            import  | 
| 6 | 
            -
            import  | 
| 7 | 
            -
            import gradio as gr
         | 
| 8 | 
            -
            from transformers import LlavaNextVideoProcessor, LlavaNextVideoForConditionalGeneration, BitsAndBytesConfig
         | 
| 9 | 
            -
             | 
| 10 | 
            -
            device = "cuda" if torch.cuda.is_available() else "cpu"
         | 
| 11 | 
            -
            model_id = "llava-hf/LLaVA-NeXT-Video-7B-hf"
         | 
| 12 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
                load_in_4bit=True,
         | 
| 15 | 
            -
                bnb_4bit_compute_dtype=torch.float16,
         | 
| 16 | 
            -
                bnb_4bit_use_double_quant=True,
         | 
| 17 | 
            -
                bnb_4bit_quant_type="nf4"
         | 
| 18 | 
            -
            )
         | 
| 19 |  | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
                 | 
| 23 | 
            -
                 | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
|  | |
|  | |
|  | |
| 26 |  | 
| 27 | 
            -
            processor =  | 
| 28 |  | 
| 29 | 
            -
            def  | 
| 30 | 
            -
                 | 
|  | |
|  | |
| 31 |  | 
| 32 | 
            -
                 | 
| 33 | 
            -
             | 
| 34 | 
            -
                os.makedirs(output_dir)
         | 
| 35 |  | 
| 36 | 
            -
                video = cv2.VideoCapture(video_path)
         | 
| 37 | 
            -
                
         | 
| 38 | 
            -
                if not video.isOpened():
         | 
| 39 | 
            -
                    raise ValueError(f"Could not open video file: {video_path}")
         | 
| 40 | 
            -
                
         | 
| 41 | 
            -
                total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
         | 
| 42 | 
            -
                interval = max(1, total_frames // num_frames)
         | 
| 43 | 
             
                frames = []
         | 
| 44 | 
            -
                 | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 45 |  | 
| 46 | 
            -
                 | 
| 47 | 
            -
                    ret, frame = video.read()
         | 
| 48 | 
            -
                    if not ret:
         | 
| 49 | 
            -
                        continue
         | 
| 50 | 
            -
                    if i % interval == 0 and len(frames) < num_frames:
         | 
| 51 | 
            -
                        cv2.imwrite(f"{output_dir}/frame_{frame_count:03d}.jpg", frame)
         | 
| 52 | 
            -
                        pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
         | 
| 53 | 
            -
                        frames.append(pil_img)
         | 
| 54 | 
            -
                        frame_count += 1
         | 
| 55 |  | 
| 56 | 
            -
                 | 
|  | |
|  | |
|  | |
|  | |
| 57 |  | 
| 58 | 
            -
                 | 
|  | |
| 59 |  | 
| 60 | 
            -
                 | 
|  | |
|  | |
|  | |
| 61 |  | 
| 62 | 
            -
            def  | 
| 63 | 
            -
                 | 
| 64 | 
            -
                     | 
| 65 | 
            -
                        "role": "user",
         | 
| 66 | 
            -
                        "content": [
         | 
| 67 | 
            -
                            {"type": "text", "text": "Analyze this gas pipe quality control video. Answer these two questions with True/False: 1) DIPPED IN WATER: Was the pipe dipped in water for testing? Look for pipe being submerged in water container. 2) BUBBLES AFTER IMMERSION: After the pipe was fully immersed (ignore initial displacement bubbles), were there any bubbles indicating a leak? Format: DIPPED IN WATER: True/False, BUBBLES AFTER IMMERSION: True/False"},
         | 
| 68 | 
            -
                            {"type": "video"},
         | 
| 69 | 
            -
                        ],
         | 
| 70 | 
            -
                    },
         | 
| 71 | 
            -
                ]
         | 
| 72 |  | 
| 73 | 
            -
                 | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 74 |  | 
| 75 | 
            -
                 | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 76 |  | 
| 77 | 
            -
                 | 
| 78 | 
            -
             | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 79 |  | 
| 80 | 
            -
                 | 
| 81 | 
            -
                     | 
| 82 | 
            -
                     | 
| 83 | 
            -
                     | 
| 84 | 
            -
                    temperature=0.3,
         | 
| 85 | 
            -
                    top_p=0.9,
         | 
| 86 | 
            -
                    top_k=50,
         | 
| 87 | 
            -
                    repetition_penalty=1.1,
         | 
| 88 | 
            -
                    pad_token_id=processor.tokenizer.eos_token_id
         | 
| 89 | 
             
                )
         | 
| 90 |  | 
| 91 | 
            -
                 | 
| 92 |  | 
| 93 | 
            -
                 | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
                 | 
| 104 | 
            -
                 | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
                 | 
| 108 | 
            -
                title="Gas Pipe Quality Control Analyzer",
         | 
| 109 | 
            -
                examples=examples,
         | 
| 110 | 
            -
                cache_examples=False
         | 
| 111 | 
            -
            )
         | 
| 112 |  | 
| 113 | 
            -
             | 
|  | 
|  | |
| 1 | 
            +
            import gradio as gr
         | 
| 2 | 
             
            import torch
         | 
| 3 | 
            +
            import cv2
         | 
| 4 | 
             
            import numpy as np
         | 
| 5 | 
            +
            from PIL import Image
         | 
| 6 | 
            +
            from transformers import AutoProcessor, LlavaNextForConditionalGeneration
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 7 |  | 
| 8 | 
            +
            MODEL_ID = "arjunanand13/gas_pipe_llava_finetunedv2"
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 9 |  | 
| 10 | 
            +
            @torch.no_grad()
         | 
| 11 | 
            +
            def load_model():
         | 
| 12 | 
            +
                processor = AutoProcessor.from_pretrained(MODEL_ID)
         | 
| 13 | 
            +
                model = LlavaNextForConditionalGeneration.from_pretrained(
         | 
| 14 | 
            +
                    MODEL_ID,
         | 
| 15 | 
            +
                    torch_dtype=torch.float16,
         | 
| 16 | 
            +
                    device_map="auto"
         | 
| 17 | 
            +
                )
         | 
| 18 | 
            +
                return processor, model
         | 
| 19 |  | 
| 20 | 
            +
            processor, model = load_model()
         | 
| 21 |  | 
| 22 | 
            +
            def extract_frames_from_video(video_path, num_frames=4):
         | 
| 23 | 
            +
                cap = cv2.VideoCapture(video_path)
         | 
| 24 | 
            +
                if not cap.isOpened():
         | 
| 25 | 
            +
                    raise ValueError(f"Cannot open video: {video_path}")
         | 
| 26 |  | 
| 27 | 
            +
                total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
         | 
| 28 | 
            +
                frame_indices = np.linspace(0, max(0, total_frames - 1), num_frames, dtype=int)
         | 
|  | |
| 29 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 30 | 
             
                frames = []
         | 
| 31 | 
            +
                for frame_idx in frame_indices:
         | 
| 32 | 
            +
                    cap.set(cv2.CAP_PROP_POS_FRAMES, frame_idx)
         | 
| 33 | 
            +
                    ret, frame = cap.read()
         | 
| 34 | 
            +
                    if ret:
         | 
| 35 | 
            +
                        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
         | 
| 36 | 
            +
                        frame_pil = Image.fromarray(frame_rgb)
         | 
| 37 | 
            +
                        frame_resized = frame_pil.resize((112, 112), Image.Resampling.LANCZOS)
         | 
| 38 | 
            +
                        frames.append(frame_resized)
         | 
| 39 |  | 
| 40 | 
            +
                cap.release()
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 41 |  | 
| 42 | 
            +
                while len(frames) < 4:
         | 
| 43 | 
            +
                    if frames:
         | 
| 44 | 
            +
                        frames.append(frames[-1].copy())
         | 
| 45 | 
            +
                    else:
         | 
| 46 | 
            +
                        frames.append(Image.new('RGB', (112, 112), color='black'))
         | 
| 47 |  | 
| 48 | 
            +
                grid_image = Image.new('RGB', (224, 224))
         | 
| 49 | 
            +
                positions = [(0, 0), (112, 0), (0, 112), (112, 112)]
         | 
| 50 |  | 
| 51 | 
            +
                for i, frame in enumerate(frames[:4]):
         | 
| 52 | 
            +
                    grid_image.paste(frame, positions[i])
         | 
| 53 | 
            +
                
         | 
| 54 | 
            +
                return grid_image
         | 
| 55 |  | 
| 56 | 
            +
            def predict_cheating(video_file):
         | 
| 57 | 
            +
                if video_file is None:
         | 
| 58 | 
            +
                    return "Please upload a video file", None
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 59 |  | 
| 60 | 
            +
                try:
         | 
| 61 | 
            +
                    grid_image = extract_frames_from_video(video_file, num_frames=4)
         | 
| 62 | 
            +
                    
         | 
| 63 | 
            +
                    prompt = """nalyze the gas‐pipe QC video and reply ONLY with valid JSON:
         | 
| 64 | 
            +
                    {"cheating": true} if any step is skipped, else {"cheating": false}.
         | 
| 65 | 
            +
                    
         | 
| 66 | 
            +
                    Required steps (no cheating):
         | 
| 67 | 
            +
                    1. Connect pipe to gas supply  
         | 
| 68 | 
            +
                    2. Submerge in water and check for bubbles  
         | 
| 69 | 
            +
                    3. Mark pipe and move to designated area  
         | 
| 70 | 
            +
                    
         | 
| 71 | 
            +
                    Cheating (any violation):
         | 
| 72 | 
            +
                    - Skipping water submersion or bubble check  
         | 
| 73 | 
            +
                    - Moving pipe without marking/testing  
         | 
| 74 | 
            +
                    
         | 
| 75 | 
            +
                    Examples:
         | 
| 76 | 
            +
                    - Dipped, checked bubbles, marked → {"cheating": false}  
         | 
| 77 | 
            +
                    - Moved without testing → {"cheating": true}  """
         | 
| 78 | 
            +
                    inputs = processor(text=prompt, images=grid_image, return_tensors="pt")
         | 
| 79 | 
            +
                    
         | 
| 80 | 
            +
                    generated_ids = model.generate(
         | 
| 81 | 
            +
                        **inputs,
         | 
| 82 | 
            +
                        max_new_tokens=50,
         | 
| 83 | 
            +
                        do_sample=False,
         | 
| 84 | 
            +
                        temperature=0.1
         | 
| 85 | 
            +
                    )
         | 
| 86 | 
            +
                    
         | 
| 87 | 
            +
                    result = processor.decode(generated_ids[0][len(inputs.input_ids[0]):], skip_special_tokens=True)
         | 
| 88 | 
            +
                    
         | 
| 89 | 
            +
                    if "true" in result.lower():
         | 
| 90 | 
            +
                        prediction = "CHEATING DETECTED"
         | 
| 91 | 
            +
                        explanation = "The system detected violations in the testing procedure."
         | 
| 92 | 
            +
                    else:
         | 
| 93 | 
            +
                        prediction = "COMPLIANT PROCEDURE"
         | 
| 94 | 
            +
                        explanation = "The testing procedure appears to follow proper protocols."
         | 
| 95 | 
            +
                    
         | 
| 96 | 
            +
                    return f"{prediction}\n\n{explanation}\n\nRaw output: {result}", grid_image
         | 
| 97 | 
            +
                    
         | 
| 98 | 
            +
                except Exception as e:
         | 
| 99 | 
            +
                    return f"Error processing video: {str(e)}", None
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            with gr.Blocks(title="Gas Pipe Quality Control Detection") as demo:
         | 
| 102 | 
            +
                gr.Markdown("# Gas Pipe Quality Control Detection")
         | 
| 103 | 
            +
                gr.Markdown("Upload a video of gas pipe testing to detect compliance violations.")
         | 
| 104 |  | 
| 105 | 
            +
                with gr.Row():
         | 
| 106 | 
            +
                    with gr.Column(scale=1):
         | 
| 107 | 
            +
                        gr.Markdown("""
         | 
| 108 | 
            +
                        ### Proper Procedure (No Cheating)
         | 
| 109 | 
            +
                        1. Connect pipe to gas supply
         | 
| 110 | 
            +
                        2. Immerse pipe in water container
         | 
| 111 | 
            +
                        3. Check for bubbles (bubbles = leak)
         | 
| 112 | 
            +
                        4. Mark pipe with marker/pen
         | 
| 113 | 
            +
                        5. Move tested pipe to designated area
         | 
| 114 | 
            +
                        """)
         | 
| 115 | 
            +
                        
         | 
| 116 | 
            +
                    with gr.Column(scale=1):
         | 
| 117 | 
            +
                        gr.Markdown("""
         | 
| 118 | 
            +
                        ### Cheating Behaviors
         | 
| 119 | 
            +
                        - Skipping water immersion test
         | 
| 120 | 
            +
                        - Moving pipe directly without testing
         | 
| 121 | 
            +
                        - Not checking for bubbles properly
         | 
| 122 | 
            +
                        - Bypassing any required step
         | 
| 123 | 
            +
                        """)
         | 
| 124 |  | 
| 125 | 
            +
                with gr.Row():
         | 
| 126 | 
            +
                    with gr.Column(scale=2):
         | 
| 127 | 
            +
                        video_input = gr.Video(
         | 
| 128 | 
            +
                            label="Upload Gas Pipe Testing Video",
         | 
| 129 | 
            +
                            height=300
         | 
| 130 | 
            +
                        )
         | 
| 131 | 
            +
                        
         | 
| 132 | 
            +
                        analyze_btn = gr.Button(
         | 
| 133 | 
            +
                            "Analyze Video", 
         | 
| 134 | 
            +
                            variant="primary",
         | 
| 135 | 
            +
                            size="lg"
         | 
| 136 | 
            +
                        )
         | 
| 137 | 
            +
                    
         | 
| 138 | 
            +
                    with gr.Column(scale=2):
         | 
| 139 | 
            +
                        result_text = gr.Textbox(
         | 
| 140 | 
            +
                            label="Detection Result",
         | 
| 141 | 
            +
                            lines=8,
         | 
| 142 | 
            +
                            max_lines=10
         | 
| 143 | 
            +
                        )
         | 
| 144 | 
            +
                        
         | 
| 145 | 
            +
                        processed_image = gr.Image(
         | 
| 146 | 
            +
                            label="Processed Video Frames (2x2 Grid)",
         | 
| 147 | 
            +
                            height=300
         | 
| 148 | 
            +
                        )
         | 
| 149 |  | 
| 150 | 
            +
                analyze_btn.click(
         | 
| 151 | 
            +
                    fn=predict_cheating,
         | 
| 152 | 
            +
                    inputs=[video_input],
         | 
| 153 | 
            +
                    outputs=[result_text, processed_image]
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 154 | 
             
                )
         | 
| 155 |  | 
| 156 | 
            +
                gr.Markdown("### Example Cases")
         | 
| 157 |  | 
| 158 | 
            +
                with gr.Row():
         | 
| 159 | 
            +
                    with gr.Column(scale=1):
         | 
| 160 | 
            +
                        gr.Markdown("""
         | 
| 161 | 
            +
                        **Cheating Examples:**
         | 
| 162 | 
            +
                        """)
         | 
| 163 | 
            +
                        
         | 
| 164 | 
            +
                    with gr.Column(scale=1):
         | 
| 165 | 
            +
                        gr.Markdown("""
         | 
| 166 | 
            +
                        **Compliant Examples:**
         | 
| 167 | 
            +
                        """)
         | 
| 168 | 
            +
                
         | 
| 169 | 
            +
                gr.Markdown("""
         | 
| 170 | 
            +
                ---
         | 
| 171 | 
            +
                Model: Fine-tuned LLaVA v1.6 Mistral 7B | Repository: arjunanand13/gas_pipe_llava_finetunedv2
         | 
| 172 | 
            +
                """)
         | 
|  | |
|  | |
|  | |
|  | |
| 173 |  | 
| 174 | 
            +
            if __name__ == "__main__":
         | 
| 175 | 
            +
                demo.launch(share=True)
         |