圖像的平移操作是將圖像的所有像素坐標(biāo)進(jìn)行水平或垂直方向移動(dòng),也就是將所有像素點(diǎn)按照給定的偏移量在水平方向沿x軸、垂直方向上沿y軸移動(dòng)。平移變換分為兩種類(lèi)型:圖像大小變化與圖像大小不變。第一種類(lèi)型保證圖像平移的完整信息,第二種圖像導(dǎo)致原始圖像的部分信息可能丟失。圖像平移變換公式如下:(不會(huì)用csdn自帶的公式編輯器,使用mathtype打出來(lái)再截圖的)
?對(duì)4*4圖像矩陣向右平移x軸一個(gè)單位,向下平移y軸一個(gè)單位,若移動(dòng)后圖像的大小保持不變,多余部分填充為白色時(shí)滿(mǎn)足:
對(duì)4*4圖像矩陣向左平移x軸一個(gè)單位,向上平移y軸一個(gè)單位,若移動(dòng)后圖像的大小變換,多余部分填充為白色時(shí)滿(mǎn)足:
?
舉例說(shuō)明:?
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
//平移操作,圖像大小不變
Mat imgTranslation1(Mat& src, int xOffset, int yOffset)
{
int nRows = src.rows;
int nCols = src.cols;
Mat result (src.size(), src.type());
//遍歷圖像
for (int i = 0; i < nRows; ++i)
{
for (int j = 0; j < nCols; ++j)
{
int x = j - xOffset;
int y = i - yOffset;
if (x >= 0 && y >= 0 && x < nCols && y < nRows)
{
result.at<Vec3b>(i, j) = src.ptr<Vec3b>(y)[x];
}
}
}
return result;
}
//平移操作,圖像大小改變
Mat imgTranslation2(Mat& src, int xOffset, int yOffset)
{
//設(shè)置平移尺寸
int nRows = src.rows + abs(yOffset);
int nCols = src.cols + abs(xOffset);
Mat result(nRows,nCols, src.type());
//遍歷圖像
for (int i = 0; i < nRows; ++i)
{
for (int j = 0; j < nCols; ++j)
{
//映射變換
int x = j - xOffset;
int y = i - yOffset;
if (x >= 0 && y >= 0 && x < nCols && y < nRows)
{
result.at<Vec3b>(i, j) = src.ptr<Vec3b>(y)[x];
}
}
}
return result;
}
int main()
{
Mat src = imread("C:\\Users\\32498\\Pictures\\16.png");
if (!src.data)
{
return -1;
}
imshow("src", src);
int xOffset = 50, yOffset = 80;
//圖像左平移不改變大小
Mat dst1 = imgTranslation1(src, xOffset, yOffset);
imshow("dst1", dst1);
//圖像左平移改變大小
Mat dst2 = imgTranslation2(src, xOffset, yOffset);
imshow("dst2", dst2);
//圖像右平移不改變大小
Mat dst3 = imgTranslation1(src, -xOffset, -yOffset);
imshow("dst3", dst3);
waitKey();
return 0;
}
運(yùn)行結(jié)果如下:?
?
?對(duì)程序中的此行代碼進(jìn)行說(shuō)明:
result.at<Vec3b>(i, j) = src.ptr<Vec3b>(y)[x];
result圖像(i,j)處的像素值等于src圖像第y行,第x個(gè)坐標(biāo)的像素值。這其實(shí)是對(duì)圖像進(jìn)行逐像素操作。
?①opencv中的Mat數(shù)據(jù)類(lèi)型指針ptr的使用
cv::Mat image = cv::Mat(400, 600, CV_8UC1); //寬400,長(zhǎng)600
uchar * data00 = image.ptr<uchar>(0);
uchar * data10 = image.ptr<uchar>(1);
uchar * data01 = image.ptr<uchar>(0)[1];
? ? ? ? 對(duì)上面的注解:(注意看這些的區(qū)別)
定義一個(gè)Mat變量image,
data00是指向image第一行第一個(gè)元素的指針
data10是指向image第二行第一個(gè)元素的指針
data01是指向image第一行第二個(gè)元素的指針?
②Vec3b類(lèi)型的含義
Vec3b可以看作是vector<uchar,3>,即一個(gè)uchar類(lèi)型,長(zhǎng)度為3的vector向量。(不知道vector容器含義的同學(xué)可以這樣理解vector,它就是一個(gè)數(shù)組,只不過(guò)這個(gè)數(shù)組的大小可以隨時(shí)改變,故稱(chēng)vector為動(dòng)態(tài)數(shù)組)
由于在opencv中讀取到的Mat圖像數(shù)據(jù)都是用uchar類(lèi)型的數(shù)據(jù)存儲(chǔ),對(duì)于RGB三通道的圖像,每個(gè)點(diǎn)的數(shù)據(jù)都是一個(gè)vec3b類(lèi)型的數(shù)據(jù)。
使用at定位方法如下:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-478084.html
Mat img=imread("123.png");
//(row,col)為所需要定位點(diǎn)的坐標(biāo)
img.at<Vec3b>(row,col)[0]=255; //修改點(diǎn)(row,col)的B通道數(shù)據(jù)
img.at<Vec3b>(row,col)[1]=255; //修改點(diǎn)(row,col)的G通道數(shù)據(jù)
img.at<Vec3b>(row,col)[2]=255; //修改點(diǎn)(row,col)的R通道數(shù)據(jù)
?同時(shí)還需要注意的是,它返回的是uchar類(lèi)型,直接使用cout輸出為字符格式,需要強(qiáng)制轉(zhuǎn)換為int 類(lèi)型之后輸出:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-478084.html
cout<<(int)img.at<Vec3b>(row,col)[0];
到了這里,關(guān)于(opencv)圖像幾何變換——平移的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!