使用Python的OpenCV,如何处理图像而不损失质量

huangapple go评论78阅读模式
英文:

with python openCV, how can i process image without loss

问题

Sure, here is the translated content of your text, excluding the code:

"我想制作一个具有多个功能(平移、旋转、翻转、剪切等)的程序,但在实现平移功能时遇到了问题。当我将图像向左移动然后向右移动时,图像的左侧部分丢失了。我认为这个问题在应用其他功能时也会出现相同的情况。

我希望在处理图像时不会丢失部分内容。

我从这里的链接中看到了类似的问题 链接,但我认为那似乎与我的情况有些不同。"

英文:

i want to make program that has several functions(translate, rotate, flip,shear..)
but i got problem with implemening the translating function.
when i move image left and then right, left part of the image is lost.
and i think this problem will be same with other functions.

import cv2 as cv
import numpy as np

img = cv.imread('tekapo.bmp')

if img is None:
    print("file not found")
    
rows, cols, ch = img.shape

#초기 x, y값 및 기본값 설정
c = (int(cols/2), int(rows/2))

def draw_line(input_img): #input_img에 선, 원 그리고 변형된 이미지 반환
    (x, y) = c
    c_img = input_img.copy()
    cv.line(c_img, c, (640, y), (0, 0, 255), 1) #x축 보조선
    cv.line(c_img, c, (x, 480), (0, 255, 0), 1) #y축 보조선
    cv.circle(c_img, c, 5, (0, 0, 255), -1)
    return c_img
    
def imshow(input_img): #input_img에 point그리고 출력, input_img는 변형 X
    c_img = input_img.copy()
    cv.imshow('C_img', draw_line(c_img))
    

def click_mouse(e, x, y, d, p):
    if e == cv.EVENT_LBUTTONDOWN:
        global c
        c = (int(x), int(y)) #좌표 저장
        imshow(copy_img)
        
    
def translate(input_img, dx, dy):
    rows, cols, ch = input_img.shape
    M = np.float32([[1, 0, dx], [0, 1, dy]])
    c_img = input_img.copy()
    c_img2 = cv.warpAffine(c_img, M, (cols, rows))
    img = c_img2.copy()
    imshow(c_img2)
    return img



copy_img = img.copy() #변형시킬 이미지가 담길 변수
imshow(copy_img)

cv.setMouseCallback('C_img', click_mouse, copy_img)

while True:
    key = cv.waitKey()
    if key == ord('t'):#오른쪽 아래로 가는 기능
        copy_img = translate(copy_img, 5, 5)
    elif key == ord('e'):#왼쪽 위로 가는 기능
        copy_img = translate(copy_img, -5, -5)
    elif key == 27:
        print(c)
        break

cv.destroyAllWindows()

i've saw similar problem from here link

but i think that looks little different situation with mine.

i want to process image without losing part of it

答案1

得分: 1

以下是您要翻译的内容:

  • 替代更新图像,我们可以更新变换矩阵 M 并将 warpAffine 应用于原始图像。这样我们保留了原始图像,只在按相关按键时每次修改变换矩阵。

  • 使用“eye”变换(去除第三行)初始化矩阵 M

      M = np.float64([[1, 0, 0], 
                      [0, 1, 0]])
    
  • 不使用 translate,实现一个更新矩阵 M 的方法。
    M 通过改变平移和当前的 M 来更新。
    更改是通过左侧乘以平移矩阵来应用的,如我[之前的回答][1]中所描述:

      def translate_mat(M, dx, dy):
          # 而不是更新图像,更新变换矩阵 M
          T0 = np.vstack((M, np.array([0, 0, 1])))  # 在 M 底部添加行 [0, 0, 1]([0, 0, 1] 应用于眼矩阵的最后一行),T0 是 3x3 矩阵。
    
          # 平移矩阵(3x3)
          T1 = np.float64([[1, 0, dx], 
                           [0, 1, dy],
                           [0, 0, 1 ]])
    
          T = T1 @ T0  # 链式变换(将平移矩阵 T1 与输入平移矩阵相乘)。
          M = T[0:2, :]  # 从 T 中删除最后一行(仿射变换的最后一行始终为 [0, 0, 1],OpenCV 转换会省略最后一行)。
          return M  # 返回更新后的 M(应用平移于输入 M 后的 M)。
    
  • 在 while 循环中,更新 M 并将 warpAffine 应用于 img(而不是更新 copy_img):

      while True:
          key = cv.waitKey()
          if key == ord('t'):  # 向右下移动功能
              # copy_img = translate(copy_img, 5, 5)
              M = translate_mat(M, 5, 5)  # 将变换应用于变换矩阵 M,而不是修改图像。
              copy_img = cv.warpAffine(img, M, (cols, rows))  # 对原始图像应用变换
              imshow(copy_img)
    

代码示例:

import cv2 as cv
import numpy as np

img = cv.imread('tekapo.bmp')

if img is None:
    print("文件未找到")

rows, cols, ch = img.shape

# 初始化 x、y 值和默认值
c = (int(cols/2), int(rows/2))

def draw_line(input_img):  # 在 input_img 上绘制线条、圆并返回转换后的图像
    (x, y) = c
    c_img = input_img.copy()
    cv.line(c_img, c, (640, y), (0, 0, 255), 1)  # x 轴辅助线
    cv.line(c_img, c, (x, 480), (0, 255, 0), 1)  # y 轴辅助线
    cv.circle(c_img, c, 5, (0, 0, 255), -1)
    return c_img

def imshow(input_img):  # 在 input_img 上显示点并输出,input_img 未经变换
    c_img = input_img.copy()
    cv.imshow('C_img', draw_line(c_img))

def click_mouse(e, x, y, d, p):
    if e == cv.EVENT_LBUTTONDOWN:
        global c
        c = (int(x), int(y))  # 保存坐标
        imshow(copy_img)

# def translate(input_img, dx, dy):
#     rows, cols, ch = input_img.shape
#     M = np.float32([[1, 0, dx], [0, 1, dy]])
#     c_img = input_img.copy()
#     c_img2 = cv.warpAffine(c_img, M, (cols, rows))
#     img = c_img2.copy()
#     imshow(c_img2)
#     return img

def translate_mat(M, dx, dy):
    # 而不是更新图像,更新平移矩阵 M
    T0 = np.vstack((M, np.array([0, 0, 1])))  # 在 M 底部添加行 [0, 0, 1]([0, 0, 1] 应用于眼矩阵的最后一行),T0 是 3x3 矩阵。

    # 平移矩阵(3x3)
    T1 = np.float64([[1, 0, dx],
                     [0, 1, dy],
                     [0, 0, 1 ]])

    T = T1 @ T0  # 链式变换(将平移矩阵 T1 与输入平移矩阵相乘)。
    M = T[0:2, :]  # 从 T 中删除最后一行(仿射变换的最后一行始终为 [0, 0, 1],OpenCV 转换会省略最后一行)。
    return M  # 返回更新后的 M(应用平移于输入 M 后的 M).

copy_img = img.copy()  # 存储要变换的图像的变量
imshow(copy_img)

cv.setMouseCallback('C_img', click_mouse, copy_img)

# 使用“eye”变换初始化 M(去除第三行)。
M = np.float64([[1, 0, 0],
                [0, 1, 0]])

rows, cols, ch = img.shape

while True:
    key = cv.waitKey()
    if key == ord('t'):  # 向右下移动功能
        # copy_img = translate(copy_img, 5, 5)
        M = translate_mat(M, 5, 5)  # 将变换应用于变换矩阵 M,而不是修改图像。
        copy_img = cv.w

<details>
<summary>英文:</summary>

Instead of updating the image, we may update the transformation matrix `M`, and apply `warpAffine` to the original image.  
That way we are preserving the original image and only modifying the transformation matrix each time the relevant key is pressed.

---

 - Initialize matrix `M` with &quot;eye&quot; transformation (without the third row):  

        M = np.float64([[1, 0, 0], 
                        [0, 1, 0]])

 - Instead of using `translate`, implement a method that updates matrix `M`.  
`M` is updated by changing the translation and the current `M`.  
Changing is applied by multiplying the translation matrix from the left, as described in my [previous answer][1]:  

        def translate_mat(M, dx, dy):
            # Instead of updating the image, update the transformation matrix M
            T0 = np.vstack((M, np.array([0, 0, 1])))  # Add row [0, 0, 1] to the bottom of M ([0, 0, 1] applies last row of eye matrix), T0 is 3x3 matrix.
            
            # Translation matrix (3x3)
            T1 = np.float64([[1, 0, dx], 
                             [0, 1, dy],
                             [0, 0, 1 ]])
        
            T = T1 @ T0  # Chain transformations (multiply translation matrix T1 by the input translation matrix).
            M = T[0:2, :]  # Remove the last row from T (the last row of affine transformations is always [0, 0, 1] and OpenCV conversion is omitting the last row).
            return M  # Return updated M (after applying the translation on the input M).

 - In the while loop, update `M` and apply `warpAffine` to `img` (instead of updating `copy_img`):  

        while True:
            key = cv.waitKey()
            if key == ord(&#39;t&#39;):#오른쪽 아래로 가는 기능
                # copy_img = translate(copy_img, 5, 5)
                M = translate_mat(M, 5, 5)  # Apply transformation to transformation matrix M instead of modifying the image.
                copy_img = cv.warpAffine(img, M, (cols, rows))  # Apply warp to the original image
                imshow(copy_img)

---

Code sample:  

    import cv2 as cv
    import numpy as np
    
    img = cv.imread(&#39;tekapo.bmp&#39;)
    
    if img is None:
        print(&quot;file not found&quot;)
        
    rows, cols, ch = img.shape
    
    #초기 x, y값 및 기본값 설정
    c = (int(cols/2), int(rows/2))
    
    def draw_line(input_img): #input_img에 선, 원 그리고 변형된 이미지 반환
        (x, y) = c
        c_img = input_img.copy()
        cv.line(c_img, c, (640, y), (0, 0, 255), 1) #x축 보조선
        cv.line(c_img, c, (x, 480), (0, 255, 0), 1) #y축 보조선
        cv.circle(c_img, c, 5, (0, 0, 255), -1)
        return c_img
        
    def imshow(input_img): #input_img에 point그리고 출력, input_img는 변형 X
        c_img = input_img.copy()
        cv.imshow(&#39;C_img&#39;, draw_line(c_img))
        
    
    def click_mouse(e, x, y, d, p):
        if e == cv.EVENT_LBUTTONDOWN:
            global c
            c = (int(x), int(y)) #좌표 저장
            imshow(copy_img)
            
        
    #def translate(input_img, dx, dy):
    #    rows, cols, ch = input_img.shape
    #    M = np.float32([[1, 0, dx], [0, 1, dy]])
    #    c_img = input_img.copy()
    #    c_img2 = cv.warpAffine(c_img, M, (cols, rows))
    #    img = c_img2.copy()
    #    imshow(c_img2)
    #    return img
    
    def translate_mat(M, dx, dy):
        # Instead of uprating the image, update the translation matrix M
        T0 = np.vstack((M, np.array([0, 0, 1])))  # Add row [0, 0, 1] to the bottom of M ([0, 0, 1] applies last row of eye matrix), T0 is 3x3 matrix.
    
        # Translation matrix (3x3)
        T1 = np.float64([[1, 0, dx], 
                         [0, 1, dy],
                         [0, 0, 1 ]])
    
        T = T1 @ T0  # Chain transformations (multiply translation matrix T1 by the input translation matrix).
        M = T[0:2, :]  # Remove the last row from T (the last row of affine transformations is always [0, 0, 1] and OpenCV conversion is omitting the last row).
        return M  # Return updated M (after applying the translation on the input M).
    
    
    
    
    copy_img = img.copy() #변형시킬 이미지가 담길 변수
    imshow(copy_img)
    
    cv.setMouseCallback(&#39;C_img&#39;, click_mouse, copy_img)
    
    # Initialize M to &quot;eye&quot; transformation (without the third row).
    M = np.float64([[1, 0, 0], 
                    [0, 1, 0]])
    
    rows, cols, ch = img.shape
    
    while True:
        key = cv.waitKey()
        if key == ord(&#39;t&#39;):#오른쪽 아래로 가는 기능
            # copy_img = translate(copy_img, 5, 5)
            M = translate_mat(M, 5, 5)  # Apply transformation to transformation matrix M instead of modifying the image.
            copy_img = cv.warpAffine(img, M, (cols, rows))  # Apply warp to the original image
            imshow(copy_img)
        elif key == ord(&#39;e&#39;):#왼쪽 위로 가는 기능
            # copy_img = translate(copy_img, -5, -5)
            M = translate_mat(M, -5, -5)  # Apply transformation to transformation matrix M instead of modifying the image.
            copy_img = cv.warpAffine(img, M, (cols, rows))  # Apply warp to the original image
            imshow(copy_img)
        elif key == 27:
            print(c)
            break
    
    cv.destroyAllWindows()

---

Sample image after pressing `&#39;t&#39;` 10 times:  
[![enter image description here][2]][2]

Sample image after pressing `&#39;t&#39;` 10 times and then pressing `&#39;e&#39;` 20 times:  
[![enter image description here][3]][3]


  [1]: https://stackoverflow.com/a/75391691/4926757
  [2]: https://i.stack.imgur.com/Pav7o.png
  [3]: https://i.stack.imgur.com/1DXMP.png

</details>



huangapple
  • 本文由 发表于 2023年4月11日 00:43:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75978933.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定