Shift image content with OpenCV

Is there a function to perform directly this operation with OpenCV?

https://github.com/opencv/opencv/issues/4413 (previously http://web.archive.org/web/20170615214220/http://code.opencv.org/issues/2299)

or you would do this

    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)));

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.

enter image description here


Here is a function I wrote, based on Zaw Lin's answer, to do frame/image shift in any direction by any amount of pixel rows or columns:

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;
}

You can simply use affine transformation translation matrix (which is for shifting points basically). cv::warpAffine() with proper transformation matrix will do the trick.

TranslationMatrix [1,0,tx ; 0,1,ty]

where: tx is shift in the image x axis, ty is shift in the image y axis, Every single pixel in the image will be shifted like that.

You can use this function which returns the translation matrix. (That is probably unnecessary for you) But it will shift the image based on offsetx and offsety parameters.

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;
}

In your case - you want to shift image 10 pixels up, you call:

translateImg(image,0,-10);

And then your image will be shifted as you desire.

Tags:

C++

Opencv