Пожалуйста, посмотрите на приведенный ниже код
import cv2
import numpy as np
from skimage import measure
def resize_image(img,size):
img = cv2.resize(img,(img.shape[0],size[1]),interpolation = cv2.INTER_AREA)
img = cv2.resize(img,size,interpolation = cv2.INTER_AREA)
return img
FINAL_TILE_WIDTH = 8
#loading image
tile_mask = cv2.imread("tile.png")
tile_mask = cv2.cvtColor(tile_mask, cv2.COLOR_BGR2GRAY)
tile_mask = resize_image(tile_mask,(36,FINAL_TILE_WIDTH))
img = cv2.imread("image.png")
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img[img < 127] = 0
img[img != 0] = 255
#final image will be stored here
final_image = np.zeros(img.shape).astype(np.uint8)
#perform connected components on the image
img = measure.label(img).astype(np.uint8)
labels = np.unique(img)
#removing noise detections
for i in labels:
if i != 0:
if len(np.where(img == i)[0]) < 30:
img[img == i] = 0
img[img != 0] = 255
#extracting the contours of all the rectangles. They might not completely be rectangles.
#but the following operation will make sure everything works fine.
_,cnts,_ = cv2.findContours(img.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
#iterate trough each contour detected
for cnt in cnts:
#extract the extreme points, here the assumption of rectangles oriented along axis is taken.
(minX ,minY)= np.min(cnt,axis = 0)[0]
(maxX, maxY) = np.max(cnt,axis = 0)[0]
width = maxX - minX
width = width - width%2
height = maxY - minY
height = height - height%2
center = (int((maxX+minX)/2),int((maxY+minY)/2))
#find if width is higher or height is higher. This will be used to orient the tile vertically or horizontally.
orientation = (width > height)
temp_tile_mask = []
tile_width = 0
tile_height = 0
#change the orientation of the tile
if orientation:
temp_tile_mask = tile_mask
tile_width = width
tile_height = FINAL_TILE_WIDTH
temp_tile_mask = resize_image(temp_tile_mask,(tile_width, tile_height))
else:
temp_tile_mask = np.transpose(tile_mask)
tile_width = FINAL_TILE_WIDTH
tile_height = height
temp_tile_mask = resize_image(temp_tile_mask,(tile_width, tile_height))
#apply the tile to the final image
final_image[center[1]-int(tile_height/2):center[1]+int(tile_height/2),
center[0]-int(tile_width/2):center[0]+int(tile_width/2)] = temp_tile_mask[:,:]
cv2.imshow("img", final_image)
cv2.waitKey(0)
На самом деле я не работал над какой-либо оптимизацией, просто пришел к требованию. Также на изображении выше, плитки выглядят очень сглаженными, для решения этой проблемы можно изменить некоторые размеры.