我正在尝试在特定坐标处将一个图像显示在另一个图像上。我已使用网络摄像头检测到 aruco 标记,并且我想在 aruco 标记上显示另一个图像。 aruco 标记可以移动,并且覆盖的图像应与标记一起移动。
有各种绘图功能以及将文本输入到图像中。我尝试过图像叠加和图像单应性。
我可以获得角点的坐标。 有没有什么函数可以在这些坐标处插入图像?
import cv2
import cv2.aruco as aruco
import glob
markerLength = 0.25
cap = cv2.VideoCapture(0)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
objpoints = []
imgpoints = []
images = glob.glob('calib_images/*.jpg')
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, (7,6),None)
if ret == True:
objpoints.append(objp)
corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
imgpoints.append(corners2)
img = cv2.drawChessboardCorners(img, (7,6), corners2,ret)
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)
calibrationFile = "calibrationFileName.xml"
calibrationParams = cv2.FileStorage(calibrationFile, cv2.FILE_STORAGE_READ)
camera_matrix = calibrationParams.getNode("cameraMatrix").mat()
dist_coeffs = calibrationParams.getNode("distCoeffs").mat()
while(True):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
aruco_dict = aruco.Dictionary_get(aruco.DICT_6X6_250)
arucoParameters = aruco.DetectorParameters_create()
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, aruco_dict, parameters=arucoParameters)
if np.all(ids != None):
rvec, tvec, _ = aruco.estimatePoseSingleMarkers(corners, markerLength, mtx, dist)
axis = aruco.drawAxis(frame, mtx, dist, rvec, tvec, 0.3)
print(ids)
display = aruco.drawDetectedMarkers(axis, corners)
display = np.array(display)
else:
display = frame
cv2.imshow('Display',display)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()```
替换图像的一部分
import cv2
import numpy as np
img1 = cv2.imread('Desert.jpg')
img2 = cv2.imread('Penguins.jpg')
img3 = img1.copy()
# replace values at coordinates (100, 100) to (399, 399) of img3 with region of img2
img3[100:400,100:400,:] = img2[100:400,100:400,:]
cv2.imshow('Result1', img3)
对两个图像进行 Alpha 混合
alpha = 0.5
img3 = np.uint8(img1*alpha + img2*(1-alpha))
cv2.imshow('Result2', img3)
@user8190410 的答案效果很好。只是为了给出一个完整的答案,为了在特定位置对两个不同大小的图像进行 alpha 混合,您可以执行以下操作:
alpha= 0.7
img1_mod = img1.copy()
img1_mod[:pos_x,:pos_y,:] = img1[:pos_x,:pos_y,:]*alpha + img2*(1-alpha)
cv2.imshow('Image1Mod', img1_mod)
实际上,我发现可以使用图像单应性来做到这一点。 这是更新后的代码。
import numpy as np
import cv2
import cv2.aruco as aruco
cap = cv2.VideoCapture(0)
while(True):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
aruco_dict = aruco.Dictionary_get(aruco.DICT_6X6_250)
arucoParameters = aruco.DetectorParameters_create()
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, aruco_dict, parameters=arucoParameters)
if np.all(ids != None):
display = aruco.drawDetectedMarkers(frame, corners)
x1 = (corners[0][0][0][0], corners[0][0][0][1])
x2 = (corners[0][0][1][0], corners[0][0][1][1])
x3 = (corners[0][0][2][0], corners[0][0][2][1])
x4 = (corners[0][0][3][0], corners[0][0][3][1])
im_dst = frame
im_src = cv2.imread("mask.jpg")
size = im_src.shape
pts_dst = np.array([x1,x2,x3,x4])
pts_src = np.array(
[
[0,0],
[size[1] - 1, 0],
[size[1] - 1, size[0] -1],
[0, size[0] - 1 ]
],dtype=float
);
h, status = cv2.findHomography(pts_src, pts_dst)
temp = cv2.warpPerspective(im_src, h, (im_dst.shape[1],im_dst.shape[0]))
cv2.fillConvexPoly(im_dst, pts_dst.astype(int), 0, 16);
im_dst = im_dst + temp
cv2.imshow('Display',im_dst)
else:
display = frame
cv2.imshow('Display',display)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
画中画
[![import cv2
import numpy as np
def picture_in_picture(main_image_path, overlay_image_path, img_ratio=4, border_size=5, x_margin=25, y_offset_adjust=-150):
"""
Overlay an image onto a main image with a white border.
Args:
main_image_path (str): Path to the main image.
overlay_image_path (str): Path to the overlay image.
img_ratio (int): The ratio to resize the overlay image height relative to the main image.
border_size (int): Thickness of the white border around the overlay image.
x_margin (int): Margin from the right edge of the main image.
y_offset_adjust (int): Adjustment for vertical offset.
Returns:
np.ndarray: The resulting image with the overlay applied.
"""
# Load images
main_image = cv2.imread(main_image_path)
overlay_image = cv2.imread(overlay_image_path)
if main_image is None or overlay_image is None:
raise FileNotFoundError("One or both images not found.")
# Resize the overlay image to 1/img_ratio of the main image height
new_height = main_image.shape\[0\] // img_ratio
new_width = int(new_height * (overlay_image.shape\[1\] / overlay_image.shape\[0\]))
overlay_resized = cv2.resize(overlay_image, (new_width, new_height))
# Add a white border to the overlay image
overlay_with_border = cv2.copyMakeBorder(
overlay_resized,
border_size, border_size, border_size, border_size,
cv2.BORDER_CONSTANT, value=\[255, 255, 255\]
)
# Determine overlay position
x_offset = main_image.shape\[1\] - overlay_with_border.shape\[1\] - x_margin
y_offset = (main_image.shape\[0\] // 2) - overlay_with_border.shape\[0\] + y_offset_adjust
# Overlay the image
main_image\[y_offset:y_offset + overlay_with_border.shape\[0\], x_offset:x_offset + overlay_with_border.shape\[1\]\] = overlay_with_border
return main_image
# Usage example
result_image = picture_in_picture("points_img.jpg", "points_img.jpg")
cv2.imshow("Image with Picture-in-Picture", result_image)
cv2.imwrite("output_image_with_border.jpg", result_image)
cv2.waitKey(0)
cv2.destroyAllWindows()][1]][1]