36

画像から始めて、サイズを変更したり、下部のサブ画像 ( ) を黒く塗りつぶしたりせずに、コンテンツを 10 ピクセル上にシフトしたいと考えてwidth x 10pxいます。

たとえば、オリジナル:

オリジナル

そしてシフト:

ずれた

この操作をOpenCVで実行する機能はありますか?

4

11 に答える 11

48

アフィン変換の平行移動行列を簡単に使用できます(これは基本的にポイントをシフトするためのものです)。cv::warpAffine()適切な変換行列を使用すると、うまくいきます。

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

ここで、 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);

そして、あなたのイメージはあなたが望むようにシフトされます。

于 2014-11-05T20:28:24.057 に答える
35

この操作を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)));
于 2013-09-28T20:44:54.167 に答える
5

これは、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;
}
于 2014-02-16T16:16:32.500 に答える
4

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

于 2020-01-12T03:30:22.333 に答える
3

この操作を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));
于 2015-11-10T03:29:22.900 に答える
0

最初にpajus_cz の answerを試してみましたが、実際にはかなり遅かったです。また、一時的なコピーを作成する余裕がないため、次のように考えました。

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ベースのソリューションよりも桁違いに高速です。(しかし、もちろん、これはあなたの場合にはまったく関係がないかもしれません。)

于 2015-09-24T09:33:00.220 に答える
0

単純な 2d フィルター/畳み込みを使用して、目標を達成できます。

OpenCVのドキュメントから直接取得。高さ (desired_displacement_y * 2 + 1) と幅 (desired_displacement_x * 2 + 1) を持つカーネルでフィルタリングする必要があります。

次に、コピー元の相対ピクセル位置を除いて、カーネルをすべてゼロに設定する必要があります。したがって、カーネルの中心が (0,0) の場合、10 ピクセルの変位に対して (10,0) を 1 に設定します。

Web サイトからサンプル コードを取得し、中央のカーネル コードを次のコードに置き換えます。

  /// 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 秒ごとに 1 ピクセルずつ上にスクロールする必要があります。描画メソッドを使用して黒いピクセルを描画することもできます。

これが機能する理由については、Wikipediaを参照してください。

于 2013-09-28T16:24:01.797 に答える
-1

一部の人にとっては便利な 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:, :, :]
于 2021-05-23T18:10:47.807 に答える