Искривление Перспективное преобразование подразделов изображения не выравнивается - PullRequest
1 голос
/ 26 апреля 2019

Я хочу деформировать подразделы изображения, чтобы проецировать его на неоднородную поверхность.В конечном счете, я хочу деформировать изображение как видимое ЗДЕСЬ , вроде как это было сделано в ЗДЕСЬ из ЭТОГО проекта.

Моя проблема в том, что когда я применяю преобразования к каждому подразделу изображения, все просто не выстраивается в линию

Это мой процесс, с помощью которого я выполняю преобразования, а затем сшиваю (кадрирую и вставляюони вместе на итоговом изображении.

  1. Получить список всех точек
  2. Создать четырехугольник области интереса (ROI) из набора из 4 точек
  3. Эти 4 точки используются для преобразования изображения с соответствующими исходными 4 точками. Это делается с помощью моей функции под названием перспектива_трансформа ()

    А. Я беру 2 набора из 4 точек и передаю их в М= cv2.getPerspectiveTransform (углы, новые углы)

    б. Затем я вызываю: warped = cv2.warpPerspective (roi, M, (ширина, высота))

  4. Послеполучение нового искаженного изображения. Я использую маски для сшивания всего вместе на основе области интереса, с которой оно было связано:

    a. Это делается функцией quadr_croped ()

    Инициализация экрана для получениянеобработанные пиксели с экрана, сохраните его в массив Numpy

    img0 = np.array(sct.grab(monitor))
    clone = img0.copy()
    total_height, total_width, channels = img0.shape
    
    xSub =int (input("How many columns would you like to divide the screen in to? (integers only)"))
    ySub =int (input("How many rows would you like to divide the screen in to? (integers only)"))
    roi_width = float(total_width/xSub)
    roi_height = float(total_height/ySub)
    
    point_list = []
    

    В-третьих: используйте 2 набора по 4 точки, чтобы деформировать перспективу изображения

    def vision_transform (image, roi, angles), newCorners, i = -1):

    corners = list (corners)
    newCorners = list (newCorners)
    height, width, pixType = image.shape
    corners = np.array([[corners[0][0],corners[0][1],corners[0][2],corners[0][3]]],np.float32)
    newCorners = np.array([[newCorners[0][0],newCorners[0][1],newCorners[0][2],newCorners[0][3]]],np.float32)
    
    
    M = cv2.getPerspectiveTransform(corners, newCorners)
    
    #warped = cv2.warpPerspective(roi, M, (width, height), flags=cv2.INTER_LINEAR)
    warped = cv2.warpPerspective(roi, M, (width, height))
    
    return warped
    

    Второе: вырезать и вставить четырехугольник в основное изображение

    def quadr_croped (mainImg, image, pts, i): # пример

    # mask defaulting to black for 3-channel and transparent for 4-channel
    # (of course replace corners with yours)
    mask = np.zeros(image.shape, dtype=np.uint8)
    roi_corners = pts #np.array([[(10,10), (300,300), (10,300)]], dtype=np.int32)
    # fill the ROI so it doesn't get wiped out when the mask is applied
    channel_count = image.shape[2]  # i.e. 3 or 4 depending on your image
    ignore_mask_color = (255,)*channel_count
    cv2.fillConvexPoly(mask, roi_corners, ignore_mask_color)
    
    
    # apply the mask
    masked_image = cv2.bitwise_and(image, mask)
    
    mainImg = cv2.bitwise_or(mainImg, mask)
    
    mainImg = mainImg + masked_image
    
    # cv2.imshow("debug: image, mainImg: " +str(i), mainImg)
    
    return mainImg
    

    Первый: функция запуска

    def draw_quadr (img1):

    #set up list for ROIquadrilateral == polygon with 4 sides
    numb_ROI = xSub * ySub
    skips =int((numb_ROI-1)/xSub)
    numb_ROI = skips + numb_ROI
    quadrilateral_list.clear()
    
    for i in range(numb_ROI):
        if not point_list[i][0] <= point_list[(i+xSub+2)][0]:
            continue
        vert_poly = np.array([[
            point_list[i],
            point_list[i+1],
            point_list[i+xSub+2], 
            point_list[i+xSub+1]
              ]], dtype=np.int32)  
    
    
        verticesPoly_old = np.array([[
            H_points_list[i],
            H_points_list[i+1],
            H_points_list[i+xSub+2], 
            H_points_list[i+xSub+1]
              ]], dtype=np.int32) 
    
        roi = img0.copy()
        # cv2.imshow("debug: roi"+str(i), roi)
        overlay = perspective_transform(
            img1,
            roi, 
            verticesPoly_old,
            vert_poly, 
            i)
    
        img1 = quadr_croped(img1,overlay,vert_poly,i)
    
    
        cv2.polylines(img1,vert_poly,True,(255,255,0))
        quadrilateral_list.append(vert_poly)
    
        pt1 = point_list[i]
        pt2 = point_list[i+xSub+2]
        cntPt = (int( (pt1[0]+pt2[0])/2),int((pt1[1]+pt2[1])/2) )
        cv2.putText(img1,str(len(quadrilateral_list)-1),cntPt,cv2.FONT_HERSHEY_SIMPLEX, 1,(0,255,0),2,cv2.LINE_AA)
        #cv2.imshow(str(i), img1) 
    return img1
    

PICTURE результатСсылки

Пожалуйста, посмотрите на них, так как они действительно хорошо показывают проблему.

Исходное изображение без искажений Original Image with no Distortion


Это изображение имеет левое смещение отцентр (без движения по оси y)

Результаты изображения искажения по оси x Results of x directional distortion image


Это изображение имеет смещение вверх от центра (без движения по оси x)

Результаты y направленного искажения изображения Results of y directional distortion image


Это изображение имеет вверх и слева отfset from the center

Результаты x и y искажения направленного изображения Results of x and y directional distortion image


Я новичок в компьютерном зрении и переполнении стека, надеюсь, я включил все, чтобы помочь описать проблему, дайте мне знать, если вам нужно знать что-нибудь еще, чтобы помочь

1 Ответ

1 голос
/ 27 апреля 2019

Конечно, в коде могут быть некоторые ошибки, потому что выходные изображения выглядят не так, как должны (а могут и не быть).Но вы никогда не получите именно то, что вы хотите, используя перспективные преобразования из-за их математической природы.А именно потому, что они нелинейные.Вы можете сделать так, чтобы углы прямоугольника совпадали, но между углами изображение масштабируется неравномерно, и вы не можете сделать эти неоднородности одинаковыми по обе стороны от разделительной линии.

Но выможет использовать аффинные преобразования, которые масштабируют изображение равномерно.И это гарантирует, что если две точки на линии совпадают, все остальные точки также совпадают.Единственная проблема здесь в том, что аффинное преобразование определяется с помощью треугольника, поэтому вам нужно будет разделить ваши четырехугольники на треугольники.Например, в следующем коде каждый четырехугольник разбит на 4 треугольника с использованием центра четырехугольника в качестве дополнительной вершины.

import numpy as np
import matplotlib.pyplot as plt
import cv2

# generate a test image
im = np.full((400,600), 255, 'u1')
h, w = im.shape
for i in range(1, w//20):
    im = cv2.line(im, (i*20, 0), (i*20, h), i*8)
for i in range(1, h//20):
    im = cv2.line(im, (0, i*20), (w, i*20), i*10)
plt.figure(figsize=(w/30, h/30))
plt.imshow(im, 'gray')
plt.show()

# Number of grid cells
nx, ny = 3, 2
p0 = np.meshgrid(np.linspace(0, w-1, nx+1, dtype='f'), np.linspace(0, h-1, ny+1, dtype='f'))
print(np.vstack(p0))
p1 = [v.copy() for v in p0]

# Move the central points
p1[0][1,1] -= 30; p1[1][1,1] -= 40
p1[0][1,2] += 20; p1[1][1,2] += 10
print(np.vstack(p1))

# Set perspective = True to see what happens if we use perspective transform
perspective = False
im1 = np.zeros_like(im)
for i in range(nx):
    for j in range(ny):
        x0, y0 = p0[0][j,i], p0[1][j,i]
        c0 = np.stack((p0[0][j:(j+2),i:(i+2)].ravel() - x0, p0[1][j:(j+2),i:(i+2)].ravel() - y0))
        c1 = np.stack((p1[0][j:(j+2),i:(i+2)].ravel(), p1[1][j:(j+2),i:(i+2)].ravel()))

        if perspective:
            ic0 = np.round(c0).astype('i')
            ic1 = np.round(c1).astype('i')
            M = cv2.getPerspectiveTransform(c0.T, c1.T)
            imw = cv2.warpPerspective(im[ic0[1,0]:ic0[1,3], ic0[0,0]:ic0[0,3]], M, (w, h))
            im1 |= cv2.fillConvexPoly(np.zeros_like(im), ic1[:,[0,1,3,2]].T, 255) & imw
        else:
            c0 = np.append(c0, np.mean(c0, axis=1, keepdims=True), 1)
            c1 = np.append(c1, np.mean(c1, axis=1, keepdims=True), 1)
            ic0 = np.round(c0).astype('i')
            ic1 = np.round(c1).astype('i')
            for ind in ([0,1,4], [1,3,4], [3,2,4], [2,0,4]):
                M = cv2.getAffineTransform(c0[:,ind].T, c1[:,ind].T)
                imw = cv2.warpAffine(im[ic0[1,0]:ic0[1,3], ic0[0,0]:ic0[0,3]], M, (w, h))
                im1 |= cv2.fillConvexPoly(np.zeros_like(im), ic1[:,ind].T, 255) & imw
plt.figure(figsize=(w/30, h/30))
plt.imshow(im1, 'gray')
plt.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...