基于网格的地毯图像变换出现镜像反转问题排查求助
图像校正网格变换镜像反转问题排查
我拍摄了一张倾斜放置在地面的地毯图像,随后为地毯所有点创建了等距网格,网格点按顺时针顺序存储(左上、右上、右下、左下)。尝试使用以下Python+OpenCV代码逐网格将该图像变换为正置地毯,但输出图像出现了镜像反转的情况,我标记在原图上的红色角标1、2、3、4位置错乱。
import cv2 import numpy as np from final.mesh import create_mesh_points import csv def generate_destination_mesh(target_size, num_divisions): target_width, target_height = target_size # Using integer division for cells; the last division might be slightly larger to cover the whole image cell_width = target_width // (num_divisions - 1) cell_height = target_height // (num_divisions - 1) extra_width = target_width % (num_divisions - 1) extra_height = target_height % (num_divisions - 1) dst_points = np.zeros((num_divisions, num_divisions, 2), dtype=np.float32) for i in range(num_divisions): for j in range(num_divisions): x = j * cell_width if j < num_divisions - 1 else j * cell_width + extra_width y = i * cell_height if i < num_divisions - 1 else i * cell_height + extra_height dst_points[i, j] = [x, y] return dst_points def transform_rug(image, mesh_points, num_divisions, target_size, dst_mesh_points, csv_filename): target_width, target_height = target_size transformed_rug = np.zeros((target_height, target_width, 3), dtype=np.uint8) with open(csv_filename, 'w', newline='') as file: writer = csv.writer(file) writer.writerow(['Cell Index i', 'Cell Index j', 'Source Points', 'Destination Points']) for i in range(49): for j in range(49): src_points = np.array([ mesh_points[i][j], # Top-left mesh_points[i][j+1], # Top-right mesh_points[i + 1][j + 1], # Bottom-right mesh_points[i+1][j] # Bottom-left ], dtype=np.float32) dst_points = np.array([ dst_mesh_points[i][j], # Top-left dst_mesh_points[i][j + 1], # Top-right dst_mesh_points[i + 1][j + 1], # Bottom-right dst_mesh_points[i + 1][j] # Bottom-left ], dtype=np.float32) matrix, _ = cv2.findHomography(src_points, dst_points) warped_cell = cv2.warpPerspective(image, matrix, (target_width, target_height)) # Place the warped cell into the correct position of the transformed rug ## Harcoding below to troubleshoot start_y = i * target_height // num_divisions end_y = (i + 1) * target_height // num_divisions start_x = j * target_width // num_divisions end_x = (j + 1) * target_width // num_divisions transformed_rug[start_y:end_y, start_x:end_x] = warped_cell[start_y:end_y, start_x:end_x] writer.writerow([i, j, src_points.tolist(), dst_points.tolist(), start_x,start_y,end_x,end_y]) return transformed_rug # Load your original rug image source_image_path = 'images/marked.png' original_rug = cv2.imread(source_image_path) # Set the number of divisions in your grid num_divisions = 50 # Change this based on your actual divisions mesh_points = create_mesh_points(source_image_path,num_divisions) csv_filename = 'grid_points.csv' # Set your target size (width, height) target_size = (1800, 2700) # Adjust as per your actual needs # Generate the destination mesh destination_mesh_points = generate_destination_mesh(target_size, num_divisions) # Transform the rug final_rug = transform_rug(original_rug, mesh_points, num_divisions, target_size,destination_mesh_points, csv_filename) # Save or display the final transformed rug #cv2.imshow('Transformed Rug', final_rug) cv2.imwrite('transformed.png', final_rug) #cv2.waitKey(0) #cv2.destroyAllWindows()
以下是源网格、目标网格及单元格放置坐标的前5组数据:
| Cell Index i | Cell Index j | Source Points | Destination Points | Start X | Start Y | End X | End Y |
|---|---|---|---|---|---|---|---|
| 0 | 0 | [[1675.0, 99.0], [1705.0, 91.0], [1686.0, 155.0], [1656.0, 161.0]] | [[0.0, 0.0], [36.0, 0.0], [36.0, 55.0], [0.0, 55.0]] | 0 | 0 | 36 | 54 |
| 0 | 1 | [[1656.0, 161.0], [1686.0, 155.0], [1666.0, 215.0], [1637.0, 222.0]] | [[36.0, 0.0], [72.0, 0.0], [72.0, 55.0], [36.0, 55.0]] | 36 | 0 | 72 | 54 |
| 0 | 2 | [[1637.0, 222.0], [1666.0, 215.0], [1645.0, 276.0], [1617.0, 284.0]] | [[72.0, 0.0], [108.0, 0.0], [108.0, 55.0], [72.0, 55.0]] | 72 | 0 | 108 | 54 |
| 0 | 3 | [[1617.0, 284.0], [1645.0, 276.0], [1623.0, 335.0], [1595.0, 344.0]] | [[108.0, 0.0], [144.0, 0.0], [144.0, 55.0], [108.0, 55.0]] | 108 | 0 | 144 | 54 |
| 0 | 4 | [[1595.0, 344.0], [1623.0, 335.0], [1601.0, 395.0], [1572.0, 405.0]] | [[144.0, 0.0], [180.0, 0.0], [180.0, 55.0], [144.0, 55.0]] | 144 | 0 | 180 | 54 |
输出图像:
原始输入图像:
我已逐行检查CSV中的网格点,未发现明显问题,但始终找不到导致镜像反转的原因。现附上用于创建网格的代码:
import cv2 import numpy as np from sourceSidePoints import process_image_and_get_side_points def create_mesh_points(source_image_path, num_divisions, dilation=40): # Load image and side points side_points, img_with_corners = process_image_and_get_side_points(source_image_path,num_divisions) # Reverse points where necessary side_points[2] = side_points[2][::-1] # Reverse bottom side points side_points[3] = side_points[3][::-1] # Reverse left side points def adjust_boundaries(side_points, dilation): # Adjusting top side (Subtract from y) top = np.array([[x, y - dilation] for x, y in side_points[0]]) # Adjusting bottom side (Add to y) bottom = np.array([[x, y + dilation] for x, y in side_points[2]]) # Adjusting right side (Add to x) right = np.array([[x + dilation, y] for x, y in side_points[1]]) # Adjusting left side (Subtract from x) left = np.array([[x - dilation, y] for x, y in side_points[3]]) return [top, right, bottom, left] # Apply the dilation to the side points adjusted_side_points = adjust_boundaries(side_points, dilation) # Assigning points to variables for clarity top = adjusted_side_points[0] right = adjusted_side_points[1] bottom = adjusted_side_points[2] left = adjusted_side_points[3] # Assuming mesh_points is a 2D array of coordinates [num_divisions][num_divisions] mesh_points = np.zeros((num_divisions, num_divisions, 2), dtype=int) # Create the mesh by directly using the points provided for i in range(num_divisions): for j in range(num_divisions): # Assign boundary points directly to ensure they remain on the edges if i == 0: mesh_points[i][j] = left[j] # First column from left elif i == num_divisions - 1: mesh_points[i][j] = right[j] # Last column from right elif j == 0: mesh_points[i][j] = top[i] # First row from top elif j == num_divisions - 1: mesh_points[i][j] = bottom[i] # Last row from bottom else: # Calculate interior mesh points horizontal_point = (left[j] * (num_divisions - i) / num_divisions) + (right[j] * i / num_divisions) vertical_point = (top[i] * (num_divisions - j) / num_divisions) + (bottom[i] * j / num_divisions) mesh_point = (horizontal_point + vertical_point) / 2 mesh_points[i][j] = mesh_point return mesh_points if __name__ == "__main__": source_image_path = '../images/marked.png' # Drawing lines and circles img_with_corners = cv2.imread(source_image_path) num_divisions = 50 mesh_points = create_mesh_points(source_image_path, num_divisions) # Drawing the horizontal lines for every row for i in range(num_divisions): for j in range(num_divisions - 1): start_point = tuple(np.round(mesh_points[i][j]).astype(int)) end_point = tuple(np.round(mesh_points[i][j + 1]).astype(int)) cv2.line(img_with_corners, start_point, end_point, (255, 0, 0, 255), 3) # Drawing the vertical lines for every column for j in range(num_divisions): for i in range(num_divisions - 1): start_point = tuple(np.round(mesh_points[i][j]).astype(int)) end_point = tuple(np.round(mesh_points[i + 1][j]).astype(int)) cv2.line(img_with_corners, start_point, end_point, (255, 0, 0, 255), 3) cv2.imshow('Mesh Overlay', img_with_corners) cv2.imwrite('mesh2.png', img_with_corners) cv2.waitKey(0) cv2.destroyAllWindows()
目前我已通过ImageMagick的Shepards畸变实现了图像校正效果,但希望能修复当前的网格变换方案,以获得更灵活的控制,恳请帮忙排查代码中的问题。
内容的提问来源于stack exchange,提问作者Karan
相关产品推荐
相关产品推荐

