import cv2
import numpy as np
import math
# 类定义:CDomPho(与之前一致)
class CDomPho:
def __init__(self):
self.m_f = self.m_Pxz = self.m_k1 = self.m_k2 = self.m_p1 = self.m_p2 = 0.0
self.m_X0 = self.m_Y0 = 0.0
self.m_cols = self.m_rows = 0
self.m_aopX = self.m_aopY = self.m_aopZ = self.m_aopP = self.m_aopO = self.m_aopK = 0.0
self.m_rotM = np.zeros(9)
self.m_ref = np.zeros(6)
def POK2M(self, p, o, k, r):
cosp = math.cos(p)
cosw = math.cos(o)
cosk = math.cos(k)
sinp = math.sin(p)
sinw = math.sin(o)
sink = math.sin(k)
r[0] = cosp * cosk - sinp * sinw * sink
r[1] = -cosp * sink - sinp * sinw * cosk
r[2] = -sinp * cosw
r[3] = cosw * sink
r[4] = cosw * cosk
r[5] = -sinw
r[6] = sinp * cosk + cosp * sinw * sink
r[7] = -sinp * sink + cosp * sinw * cosk
r[8] = cosp * cosw
def SetPara(self, aopX, aopY, aopZ, aopP, aopO, aopK,
f, pxz, cols, rows, k1, k2, p1, p2, X0, Y0):
self.m_rotM = np.zeros(9)
self.POK2M(aopP, aopO, aopK, self.m_rotM)
self.m_aopX, self.m_aopY, self.m_aopZ = aopX, aopY, aopZ
self.m_aopP, self.m_aopO, self.m_aopK = aopP, aopO, aopK
self.m_f, self.m_Pxz = f, pxz
self.m_k1, self.m_k2, self.m_p1, self.m_p2 = k1, k2, p1, p2
self.m_X0, self.m_Y0 = X0, Y0
self.m_cols, self.m_rows = cols, rows
self.m_ref[0] = -(cols / 2) * pxz
self.m_ref[1] = pxz
self.m_ref[2] = 0
self.m_ref[3] = -(rows / 2) * pxz
self.m_ref[4] = 0
self.m_ref[5] = -pxz
def Scan2Pho(self, scX, scY):
phoX = self.m_ref[0] + self.m_ref[1] * scX - self.m_ref[2] * scY
phoY = self.m_ref[3] + self.m_ref[4] * scX - self.m_ref[5] * scY
if abs(self.m_k1) > 1e-12:
x, y = phoX, phoY
r2 = x * x + y * y
r4 = r2 * r2
dx = x * (self.m_k1 * r2 + self.m_k2 * r4) + self.m_p1 * (r2 + 2 * x * x) + 2 * self.m_p2 * x * y
dy = y * (self.m_k1 * r2 + self.m_k2 * r4) + self.m_p2 * (r2 + 2 * y * y) + 2 * self.m_p1 * x * y
phoX -= dx
phoY -= dy
return phoX, phoY
def Pho2Scan(self, phoX, phoY):
if abs(self.m_k1) > 1e-12:
x, y = phoX, phoY
r2 = x * x + y * y
r4 = r2 * r2
dx0 = x * (self.m_k1 * r2 + self.m_k2 * r4) + self.m_p1 * (r2 + 2 * x * x) + 2 * self.m_p2 * x * y
dy0 = y * (self.m_k1 * r2 + self.m_k2 * r4) + self.m_p2 * (r2 + 2 * y * y) + 2 * self.m_p1 * x * y
x = phoX + dx0
y = phoY + dy0
r2 = x * x + y * y
r4 = r2 * r2
dx = x * (self.m_k1 * r2 + self.m_k2 * r4) + self.m_p1 * (r2 + 2 * x * x) + 2 * self.m_p2 * x * y
dy = y * (self.m_k1 * r2 + self.m_k2 * r4) + self.m_p2 * (r2 + 2 * y * y) + 2 * self.m_p1 * x * y
phoX += dx
phoY += dy
phoX -= self.m_ref[0]
phoY -= self.m_ref[3]
tt = self.m_ref[1] * self.m_ref[5] - self.m_ref[2] * self.m_ref[4]
scX = (self.m_ref[5] * phoX - self.m_ref[2] * phoY) / tt
scY = -(-self.m_ref[4] * phoX + self.m_ref[1] * phoY) / tt
return scX, scY
def PhoZ2Grd(self, px, py, gz):
A = self.m_rotM[0] * px + self.m_rotM[1] * py - self.m_rotM[2] * self.m_f
B = self.m_rotM[3] * px + self.m_rotM[4] * py - self.m_rotM[5] * self.m_f
C = self.m_rotM[6] * px + self.m_rotM[7] * py - self.m_rotM[8] * self.m_f
if abs(C) > 1e-12:
N = (gz - self.m_aopZ) / C
else:
N = 0.0
gx = self.m_aopX + A * N
gy = self.m_aopY + B * N
return gx, gy
def Grd2Pho_(self, gx, gy, gz):
dx = gx - self.m_aopX
dy = gy - self.m_aopY
dz = gz - self.m_aopZ
denom = self.m_rotM[2] * dx + self.m_rotM[5] * dy + self.m_rotM[8] * dz
fm = -self.m_f / denom if abs(denom) > 1e-12 else 0
px = (self.m_rotM[0] * dx + self.m_rotM[3] * dy + self.m_rotM[6] * dz) * fm
py = (self.m_rotM[1] * dx + self.m_rotM[4] * dy + self.m_rotM[7] * dz) * fm
return px, py
def ImgZ2Grd(self, xyz):
results = []
for i in range(0, len(xyz), 3):
scX, scY, Z = xyz[i], xyz[i + 1], xyz[i + 2]
phoX, phoY = self.Scan2Pho(scX, scY)
gx, gy = self.PhoZ2Grd(phoX, phoY, Z)
results.extend([gx, gy, Z])
return results
def Grd2Img(self, gx, gy, gz):
px, py = self.Grd2Pho_(gx, gy, gz)
scX, scY = self.Pho2Scan(px, py)
return scX, scY
# 鼠标交互相关全局变量
scale = 1.0
angle = 0.0
offset_x = 0
offset_y = 0
last_mouse_pos = (0, 0)
dragging = False
def mouse_callback(event, x, y, flags, param):
global scale, angle, offset_x, offset_y, dragging, last_mouse_pos
if event == cv2.EVENT_MBUTTONDOWN:
dragging = True
last_mouse_pos = (x, y)
elif event == cv2.EVENT_MOUSEMOVE and dragging:
dx = x - last_mouse_pos[0]
dy = y - last_mouse_pos[1]
offset_x += dx
offset_y += dy
last_mouse_pos = (x, y)
update_display()
elif event == cv2.EVENT_MBUTTONUP:
dragging = False
elif event == cv2.EVENT_MOUSEWHEEL:
if flags > 0:
scale *= 1.1
else:
scale /= 1.1
update_display()
elif event == cv2.EVENT_RBUTTONDOWN:
angle += 10
if angle >= 360:
angle -= 360
update_display()
def update_display():
"""根据当前参数更新显示图像"""
global domImg, scale, angle, offset_x, offset_y
center = (domImg.shape[1] // 2, domImg.shape[0] // 2)
M_scale = cv2.getRotationMatrix2D(center, 0, scale)
M_rot = cv2.getRotationMatrix2D(center, angle, 1)
M_translate = np.float32([[1, 0, offset_x], [0, 1, offset_y]])
M = M_translate @ M_rot @ M_scale
transformed_img = cv2.warpAffine(domImg, M, (domImg.shape[1], domImg.shape[0]))
cv2.imshow('Orthophoto', transformed_img)
if __name__ == "__main__":
try:
with open(r'D:\shuiwei\para.txt') as file:
file.readline() # 跳过第一行
params = list(map(float, file.readline().split()))
except Exception as e:
print(f"读取参数文件时出错: {e}")
exit(1)
aopX, aopY, aopZ, aopP, aopO, aopK = params[0:6]
f, Pxz, k1, k2, p1, p2, X0, Y0 = params[6:14]
m_img = cv2.imread(r'D:\shuiwei\1.jpg')
if m_img is None:
raise FileNotFoundError("无法读取图像文件 ")
rows, cols = m_img.shape[:2]
dompho = CDomPho()
dompho.SetPara(aopX, aopY, aopZ, aopP, aopO, aopK,
f, Pxz, cols, rows, k1, k2, p1, p2, X0, Y0)
corPt = [0.0, 0.0, 64.3,
cols, 0, 64.3,
0, rows, 64.3,
cols, rows, 64.3]
grd_coords = dompho.ImgZ2Grd(corPt)
gxs = grd_coords[0::3]
gys = grd_coords[1::3]
mingx, maxgx = min(gxs), max(gxs)
mingy, maxgy = min(gys), max(gys)
dx = maxgx - mingx
dy = maxgy - mingy
resolution = 0.5
domCols = int(dx / resolution) + 1
domRows = int(dy / resolution) + 1
domImg = np.zeros((domRows, domCols, 3), dtype=np.uint8)
h = 64.3
gy = mingy
total_pixels = domRows * domCols
processed = 0
for r in range(domRows):
gx = mingx
for c in range(domCols):
ix, iy = dompho.Grd2Img(gx, gy, h)
i = int(ix + 0.5)
j = int(iy + 0.5)
if 0 <= i < cols and 0 <= j < rows:
domImg[r, c] = m_img[rows - 1 - j, i]
gx += resolution
processed += 1
if processed % 10000 == 0:
percent = processed / total_pixels * 100
print(f"处理进度: {percent:.2f}%")
gy += resolution
cv2.namedWindow('Orthophoto', cv2.WINDOW_NORMAL)
cv2.setMouseCallback('Orthophoto', mouse_callback)
update_display()
print("按 ESC 键退出程序")
while True:
key = cv2.waitKey(1)
if key == 27:
break
cv2.destroyAllWindows()
Traceback (most recent call last):
File "D:\水位检测\正射校正\基于控制点的单应性变换.py", line 249, in <module>
update_display()
File "D:\水位检测\正射校正\基于控制点的单应性变换.py", line 178, in update_display
M = M_translate @ M_rot @ M_scale
~~~~~~~~~~~~^~~~~~~
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2 is different from 3)输出修改后的完整代码