You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在OpenCV中利用霍夫变换得到的倾斜线获取ROI(矩阵)

Great question! OpenCV doesn’t have a built-in function specifically for extracting ROIs based on arbitrary straight lines (since the standard ROI is always axis-aligned), but you can absolutely build this functionality yourself using basic geometric operations and masking. Here’s how to do it step by step for your scenario of splitting an image along slightly tilted vertical lines from Hough Transform:

Step 1: Convert Hough Lines to Image Boundary Points

First, we need to take the rho and theta values output by the Hough Transform and convert them into actual points where each line intersects the top and bottom edges of your image. This gives us clear endpoints for each tilted vertical line within the image frame.

import cv2
import numpy as np

def hough_line_to_image_points(rho, theta, img_shape):
    h, w = img_shape[:2]
    a = np.cos(theta)
    b = np.sin(theta)
    
    # Calculate base point on the line
    x0 = a * rho
    y0 = b * rho
    
    # Find intersection with top edge (y=0)
    if b != 0:
        y_top = 0
        x_top = int((rho - y_top * b) / a) if a != 0 else int(x0)
    else:
        x_top = int(x0)
        y_top = 0
    
    # Find intersection with bottom edge (y=h-1)
    if b != 0:
        y_bottom = h - 1
        x_bottom = int((rho - y_bottom * b) / a) if a != 0 else int(x0)
    else:
        x_bottom = int(x0)
        y_bottom = h - 1
    
    # Clamp coordinates to image boundaries
    x_top = max(0, min(w - 1, x_top))
    x_bottom = max(0, min(w - 1, x_bottom))
    
    return (x_top, y_top), (x_bottom, y_bottom)

Step 2: Sort Lines by Horizontal Position

Since you want to split the image between consecutive vertical lines, sort the lines based on their horizontal position (e.g., the x-coordinate of their top intersection point) to ensure we process them left to right.

# Assume `lines` is the output from cv2.HoughLines()
# lines shape: (N, 1, 2) where each entry is (rho, theta)
points_list = []
for line in lines:
    rho, theta = line[0]
    top_point, bottom_point = hough_line_to_image_points(rho, theta, img.shape)
    points_list.append((top_point, bottom_point))

# Sort lines by the x-coordinate of their top edge intersection
points_list.sort(key=lambda x: x[0][0])

Step 3: Create Polygon Masks & Extract Sub-Images

For each pair of consecutive lines (and the image edges), define a quadrilateral region that represents the area between them. Use this shape to create a binary mask, then extract and crop the region to get your sub-images.

sub_images = []
h, w = img.shape[:2]

# Start with the left edge of the image as the first boundary
prev_top = (0, 0)
prev_bottom = (0, h - 1)

# Process each line to create segments between previous boundary and current line
for curr_top, curr_bottom in points_list:
    # Define the quadrilateral vertices for the segment
    polygon_pts = np.array([
        prev_top, curr_top, curr_bottom, prev_bottom
    ], dtype=np.int32)
    polygon_pts = polygon_pts.reshape((-1, 1, 2))
    
    # Create mask for the segment
    mask = np.zeros((h, w), dtype=np.uint8)
    cv2.fillPoly(mask, [polygon_pts], 255)
    
    # Extract the segment using the mask
    segment = cv2.bitwise_and(img, img, mask=mask)
    
    # Crop to the minimal bounding rectangle of the polygon
    x, y, seg_w, seg_h = cv2.boundingRect(polygon_pts)
    cropped_segment = segment[y:y+seg_h, x:x+seg_w]
    sub_images.append(cropped_segment)
    
    # Update previous boundary to current line
    prev_top, prev_bottom = curr_top, curr_bottom

# Add the final segment from the last line to the right image edge
final_top = (w - 1, 0)
final_bottom = (w - 1, h - 1)
polygon_pts = np.array([
    prev_top, final_top, final_bottom, prev_bottom
], dtype=np.int32)
polygon_pts = polygon_pts.reshape((-1, 1, 2))

mask = np.zeros((h, w), dtype=np.uint8)
cv2.fillPoly(mask, [polygon_pts], 255)
segment = cv2.bitwise_and(img, img, mask=mask)
x, y, seg_w, seg_h = cv2.boundingRect(polygon_pts)
cropped_segment = segment[y:y+seg_h, x:x+seg_w]
sub_images.append(cropped_segment)

# Now sub_images contains your split A, B, C, etc.

Key Notes & Tips

  • Clean Up Hough Lines: Before processing, filter or deduplicate lines from the Hough Transform to avoid overlapping or redundant boundaries. You can use clustering (like k-means) on line parameters to group similar lines.
  • Handle Extreme Tilts: If lines are heavily tilted, double-check the intersection calculation to ensure points stay within the image frame.
  • Color Images: This code works for both grayscale and color images since cv2.bitwise_and operates on all channels automatically.
  • Non-Rectangular Output: If you want to keep the original polygonal shape instead of cropping to a rectangle, you can skip the bounding rect step and work with the masked image directly.

内容的提问来源于stack exchange,提问作者amatuer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:32:49