Created
July 25, 2026 13:45
-
-
Save JordaanFouche/4d54d0e2630e38e8d17aec26b419ddbe to your computer and use it in GitHub Desktop.
"OTV Fracture Analysis - Corrections Needed"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def detect_fractures(self, image, depth_top, depth_bottom): | |
| """Detect fractures in the image using specified method""" | |
| # ... existing edge detection code ... | |
| # For each detected line, calculate fracture parameters | |
| fractures = [] | |
| for line in lines: | |
| x1, y1, x2, y2 = line[0] | |
| # Calculate the angle (dip) | |
| angle_rad = np.arctan2(y2 - y1, x2 - x1) | |
| dip_deg = abs(np.degrees(angle_rad)) | |
| if dip_deg > 90: | |
| dip_deg = 180 - dip_deg | |
| # Calculate depth (midpoint of the fracture) | |
| depth_pixel = (y1 + y2) / 2 | |
| depth_m = depth_top + (depth_pixel / self.pixels_per_meter) | |
| # Calculate length along borehole wall (arc length) | |
| # The x-coordinate represents position around the borehole circumference | |
| # The actual length is the arc length along the borehole wall | |
| dx_pixels = x2 - x1 | |
| dy_pixels = y2 - y1 | |
| length_pixels = np.sqrt(dx_pixels**2 + dy_pixels**2) | |
| # Convert to meters using the circumference | |
| # The image width represents the full circumference | |
| length_m = (length_pixels / self.image_width) * self.circumference_m | |
| # Calculate azimuth (dip direction) from x-position | |
| # In OTV images, x=0 maps to North (or reference direction) | |
| x_center = (x1 + x2) / 2 | |
| azimuth_deg = (x_center / self.image_width) * 360 | |
| # Apply magnetic declination correction | |
| true_azimuth = (azimuth_deg - self.declination) % 360 | |
| # Estimate aperture from line thickness | |
| aperture_mm = self.estimate_aperture_from_line(line, image) | |
| fractures.append({ | |
| 'depth': depth_m, | |
| 'dip': dip_deg, | |
| 'azimuth': true_azimuth, | |
| 'length': length_m, | |
| 'aperture': aperture_mm | |
| }) | |
| return fractures | |
| def estimate_aperture_from_line(self, line, image): | |
| """Estimate fracture aperture from the line in the image""" | |
| x1, y1, x2, y2 = line[0] | |
| # Calculate line direction | |
| dx = x2 - x1 | |
| dy = y2 - y1 | |
| length = np.sqrt(dx*dx + dy*dy) | |
| if length < 3: | |
| return 0.05 # Very small fracture | |
| # Sample the line and estimate width from intensity profile | |
| num_samples = min(30, int(length)) | |
| widths = [] | |
| for i in range(num_samples): | |
| t = i / num_samples | |
| x = int(x1 + t * dx) | |
| y = int(y1 + t * dy) | |
| # Get the intensity profile perpendicular to the line | |
| # Simple approach: look at the line thickness in the Hough transform | |
| # The line width can be estimated from the accumulator values | |
| pass | |
| # For now, use a heuristic based on line length and pixel intensity | |
| # This is a simplified approach - in practice, you'd use the actual image data | |
| line_thickness_pixels = max(1.0, length / 100) | |
| # Convert to millimeters using the scale factor | |
| aperture_mm = line_thickness_pixels / self.scale_factor | |
| # Ensure reasonable bounds | |
| aperture_mm = max(0.01, min(10.0, aperture_mm)) | |
| return aperture_mm | |
| def detect_fractures_hybrid(self, edges, image): | |
| """Hybrid detection: combine Hough transform and contour detection""" | |
| # Hough Transform detection | |
| lines = cv2.HoughLinesP( | |
| edges, | |
| rho=1, | |
| theta=np.pi/180, | |
| threshold=self.hough_threshold, | |
| minLineLength=self.min_line_length, | |
| maxLineGap=self.max_line_gap | |
| ) | |
| # Contour detection | |
| contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
| all_lines = [] | |
| # Add Hough lines | |
| if lines is not None: | |
| for line in lines: | |
| all_lines.append(line) | |
| # Add contour-based lines (simplified as line segments) | |
| for contour in contours: | |
| if len(contour) > 5: | |
| # Fit a line to the contour | |
| [vx, vy, x0, y0] = cv2.fitLine(contour, cv2.DIST_L2, 0, 0.01, 0.01) | |
| # Convert to line segment | |
| length = np.sqrt(vx*vx + vy*vy) | |
| if length > 0: | |
| # Extend the line to cover the contour extent | |
| pts = contour.reshape(-1, 2) | |
| min_dist = np.min(pts, axis=0) | |
| max_dist = np.max(pts, axis=0) | |
| # Create line segment from the fitted line | |
| # ... (simplified for brevity) | |
| return all_lines |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment