从图像开始,我想将其内容向上移动 10 个像素,而不改变大小并将width x 10px
底部的子图像 ( ) 填充为黑色。
比如原文:
和转移:
是否有任何功能可以使用OpenCV执行此操作?
您可以简单地使用仿射变换平移矩阵(基本上用于移动点)。cv::warpAffine()
使用适当的变换矩阵就可以了。
其中: tx是图像 x 轴的偏移, ty是图像 y 轴的偏移,图像中的每个像素都会像这样偏移。
您可以使用此函数返回平移矩阵。(这对你来说可能是不必要的)但它会根据offsetx
和offsety
参数移动图像。
Mat translateImg(Mat &img, int offsetx, int offsety){
Mat trans_mat = (Mat_<double>(2,3) << 1, 0, offsetx, 0, 1, offsety);
warpAffine(img,img,trans_mat,img.size());
return img;
}
在您的情况下-您想将图像向上移动 10 个像素,您可以调用:
translateImg(image,0,-10);
然后你的形象就会随心所欲地改变。
是否有使用 OpenCV 直接执行此操作的功能?
https://github.com/opencv/opencv/issues/4413(以前 http://web.archive.org/web/20170615214220/http://code.opencv.org/issues/2299)
或者你会这样做
cv::Mat out = cv::Mat::zeros(frame.size(), frame.type());
frame(cv::Rect(0,10, frame.cols,frame.rows-10)).copyTo(out(cv::Rect(0,0,frame.cols,frame.rows-10)));
这是我根据 Zaw Lin 的回答编写的一个函数,用于在任何方向上按任意数量的像素行或列进行帧/图像移位:
enum Direction{
ShiftUp=1, ShiftRight, ShiftDown, ShiftLeft
};
cv::Mat shiftFrame(cv::Mat frame, int pixels, Direction direction)
{
//create a same sized temporary Mat with all the pixels flagged as invalid (-1)
cv::Mat temp = cv::Mat::zeros(frame.size(), frame.type());
switch (direction)
{
case(ShiftUp) :
frame(cv::Rect(0, pixels, frame.cols, frame.rows - pixels)).copyTo(temp(cv::Rect(0, 0, temp.cols, temp.rows - pixels)));
break;
case(ShiftRight) :
frame(cv::Rect(0, 0, frame.cols - pixels, frame.rows)).copyTo(temp(cv::Rect(pixels, 0, frame.cols - pixels, frame.rows)));
break;
case(ShiftDown) :
frame(cv::Rect(0, 0, frame.cols, frame.rows - pixels)).copyTo(temp(cv::Rect(0, pixels, frame.cols, frame.rows - pixels)));
break;
case(ShiftLeft) :
frame(cv::Rect(pixels, 0, frame.cols - pixels, frame.rows)).copyTo(temp(cv::Rect(0, 0, frame.cols - pixels, frame.rows)));
break;
default:
std::cout << "Shift direction is not set properly" << std::endl;
}
return temp;
}
this link maybe help this question, thanks
import cv2
import numpy as np
img = cv2.imread('images/input.jpg')
num_rows, num_cols = img.shape[:2]
translation_matrix = np.float32([ [1,0,70], [0,1,110] ])
img_translation = cv2.warpAffine(img, translation_matrix, (num_cols, num_rows))
cv2.imshow('Translation', img_translation)
cv2.waitKey()
and tx and ty could control the shift pixels on x and y direction respectively.
由于目前没有 Python 解决方案,而使用 Python 移动图像的 Google 搜索会将您带到此页面,这里有一个使用 Python 的 Python 解决方案np.roll()
沿 x 轴移动
import cv2
import numpy as np
image = cv2.imread('1.jpg')
shift = 40
for i in range(image.shape[1] -1, image.shape[1] - shift, -1):
image = np.roll(image, -1, axis=1)
image[:, -1] = 0
cv2.imshow('image', image)
cv2.waitKey()
沿 y 轴移动
import cv2
import numpy as np
image = cv2.imread('1.jpg')
shift = 40
for i in range(image.shape[0] -1, image.shape[0] - shift, -1):
image = np.roll(image, -1, axis=0)
image[-1, :] = 0
cv2.imshow('image', image)
cv2.waitKey()
h, w = image.shape # for gray image
shift = 100 # any legal number 0 < x < h
img[:h-shift, :] = img[shift:, :]
img[h-shift:, :] = 0
是否有使用 OpenCV 直接执行此操作的功能?
http://code.opencv.org/issues/2299
或者你会这样做
cv::Mat out = cv::Mat::zeros(frame.size(), frame.type()); frame(cv::Rect(0,10, frame.cols,frame.rows-10)).copyTo(out(cv::Rect(0,0,frame.cols,frame.rows-10)));
上面的代码只能用于移动到一侧(向左和向上)。下面的代码是上面代码的扩展版本,可用于向各个方向移动。
int shiftCol = 10;
int shiftRow = 10;
Rect source = cv::Rect(max(0,-shiftCol),max(0,-shiftRow), frame.cols-abs(shiftCol),frame.rows-abs(shiftRow));
Rect target = cv::Rect(max(0,shiftCol),max(0,shiftRow),frame.cols-abs(shiftCol),frame.rows-abs(shiftRow));
frame(source).copyTo(out(target));
我的实现使用与接受的答案相同的方法,但是它可以向任何方向移动......
using namespace cv;
//and whatever header 'abs' requires...
Mat offsetImageWithPadding(const Mat& originalImage, int offsetX, int offsetY, Scalar backgroundColour){
cv::Mat padded = Mat(originalImage.rows + 2 * abs(offsetY), originalImage.cols + 2 * abs(offsetX), CV_8UC3, backgroundColour);
originalImage.copyTo(padded(Rect(abs(offsetX), abs(offsetY), originalImage.cols, originalImage.rows)));
return Mat(padded,Rect(abs(offsetX) + offsetX, abs(offsetY) + offsetY, originalImage.cols, originalImage.rows));
}
//example use with black borders along the right hand side and top:
Mat offsetImage = offsetImageWithPadding(originalImage, -10, 6, Scalar(0,0,0));
它取自我自己的工作代码,但有些变量发生了变化,如果它不能编译,很可能只是一件小事需要改变——但你明白了。abs函数...
您可以使用简单的 2d 过滤器/卷积来实现您的目标:
直接取自OpenCV 文档。您需要使用具有高度 (desired_displacement_y * 2 + 1) 和宽度 (desired_displacement_x * 2 + 1) 的内核进行过滤。
然后,您需要将内核设置为全零,但要复制的相对像素位置除外。因此,如果您的内核中心是 (0,0),您可以将 (10,0) 设置为 1,以实现 10 个像素的位移。
从网站上获取示例代码,将中间的内核代码替换为以下内容:
/// Update kernel size for a normalized box filter
kernel_size = 1 + ind * 2; //Center pixel plus displacement diameter (=radius * 2)
kernel = Mat::zeros( kernel_size, kernel_size, CV_32F );
kernel.at<float>(ind * 2, ind) = 1.0f; // Indices are zero-based, not relative
/// Apply filter
filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_CONSTANT );
注意 filter2D 中的 BORDER_CONSTANT!您现在应该运行该示例并让图片每 0.5 秒向上滚动一个像素。您还可以使用绘图方法绘制黑色像素。
关于为什么会这样,请参阅Wikipedia。
我首先尝试使用pajus_cz 的答案,但在实践中速度很慢。另外,我买不起临时副本,所以我想出了这个:
void translateY(cv::Mat& image, int yOffset)
{
int validHeight = std::max(image.rows - abs(yOffset), 0);
int firstSourceRow = std::max(-yOffset, 0);
int firstDestinationRow = std::max(yOffset, 0);
memmove(image.ptr(firstDestinationRow),
image.ptr(firstSourceRow),
validHeight * image.step);
}
它比warpAffine
基于 - 的解决方案快几个数量级。(但这当然可能与您的情况完全无关。)
Python 代码有些人可能会觉得有用。
h, w, c = image.shape
shift = 4 #set shift magnitude
img_shift_right = np.zeros(image.shape)
img_shift_down = np.zeros(image.shape)
img_shift_left = np.zeros(image.shape)
img_shift_up = np.zeros(image.shape)
img_shift_right[:,shift:w, :] = image[:,:w-shift, :]
img_shift_down[shift:h, :, :] = image[:h-shift, :, :]
img_shift_left[:,:w-shift, :] = image[:,shift:, :]
img_shift_up[:h-shift, :, :] = image[shift:, :, :]