图像变换:opencv基于树莓派和Android端分别实现
扫描二维码
随时随地手机看文章
点击上方蓝字关注我哦~
01
前言
最近笔者在一些项目上需要对图像做些变换操作,这些操作opencv基本上都帮我们实现了,但是在linux系统和Android系统实现起来还是有些区别的,在这里和大家分享下。
02
知识点
由四对点计算透射变换
函数原型:
CvMat* cvGetPerspectiveTransform( const CvPoint2D32f*src, const CvPoint2D32f* dst,
CvMat*map_matrix );
参数含义:
src:输入图像的四边形顶点坐标。
dst:输出图像的相应的四边形顶点坐标。
map_matrix:指向3×3输出矩阵的指针。
函数cvGetPerspectiveTransform计算满足以下关系的透射变换矩阵:
这里,dst(i)= (x'i,y'i),src(i)= (xi,yi),i = 0..3。
对图像进行透视变换
函数原型:
void cvWarpPerspective( const CvArr* src, CvArr* dst,const CvMat* map_matrix,
int flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,
CvScalar fillval=cvScalarAll(0) );
src:输入图像.
dst:输出图像.
map_matrix:3×3 变换矩阵
flags:插值方法和以下开关选项的组合:
· CV_WARP_FILL_OUTLIERS- 填充所有缩小图像的像素。如果部分象素落在输入图像的边界外,那么它们的值设定为 fillval.
· CV_WARP_INVERSE_MAP- 指定 matrix 是输出图像到输入图像的反变换,因此可以直接用来做象素插值。否则, 函数从 map_matrix 得到反变换。
fillval:用来填充边界外面的值。
函数 cvWarpPerspective 利用下面指定矩阵变换输入图像:
如果没有指定 CV_WARP_INVERSE_MAP:
否则:
要变换稀疏矩阵,使用 cxcore 中的函数 cvTransform。
03
树莓派实现
using namespace std;
using namespace cv;
int main()
{
Point2f Ceneter(640, 512);// 1-5;在图片上确定5个矫正点 坐标参数可调整 图片默认size;1280*1024
Point2f left_up(485, 510);
Point2f right_up(840, 425);
Point2f right_down(847, 510);
Point2f left_down(487, 567);
const Point2f src[4] = { left_up, right_up, right_down, left_down }; //6;4个坐标数组(上下左右4个坐标)
float half_H = 42; //图片高度调整范围
float half_W = 280; //图片宽度调整范围
float scale = 0.8; //调整系数
float new_half_H = half_H * scale;//同7
float new_half_W = half_W * scale;//同8
float shift_x =100;//rng.uniform(50.f, 100.f);//新坐标x轴调整参数
float shift_y = -20; //新坐标y轴调整参数
Point2f left_upX(Ceneter.x + shift_x - new_half_W, Ceneter.y + shift_y - new_half_H);//14-17;生成上下左右4个新坐标
Point2f right_upX(Ceneter.x + shift_x + new_half_W, Ceneter.y + shift_y - new_half_H);
Point2f right_downX(Ceneter.x + shift_x + new_half_W, Ceneter.y + shift_y + new_half_H);
Point2f left_downX(Ceneter.x + shift_x - new_half_W, Ceneter.y + shift_y + new_half_H);
Mat perspectivemat;
const Point2f dst[4] = { left_upX, right_upX, right_downX, left_downX };//
Mat TransMat = getPerspectiveTransform(src, dst);
Mat Transimg; //新图片矩阵
//Shape shape(1, 3, 720, 1280);
int Train_Channel_size_ = 3;//shape.C;
Mat handimg = cv::imread("B.jpg");
//cv::Mat& handimg = cv::imread("./000001.jpg", -1);
if (!handimg.data) {
// return 0;
}
//std::vector<ResultBox> one_img_bboxes_target;
Size img_size;
//Get_Boxes_Info(image_path + ".xml", one_img_bboxes_target, img_size);
Mat image_reclor;
if (handimg.channels() == 3 && Train_Channel_size_ == 1)
cvtColor(handimg, image_reclor, cv::COLOR_BGR2GRAY);
else if (handimg.channels() == 4 && Train_Channel_size_ == 1)
cvtColor(handimg, image_reclor, cv::COLOR_BGRA2GRAY);
else if (handimg.channels() == 4 && Train_Channel_size_ == 3)
cvtColor(handimg, image_reclor, cv::COLOR_BGRA2BGR);
else if (handimg.channels() == 1 && Train_Channel_size_ == 3)
cvtColor(handimg, image_reclor, cv::COLOR_GRAY2BGR);
else
image_reclor = handimg;
cv::Mat img_resize;
if (image_reclor.size() != cv::Size(1280, 720)) {
resize(image_reclor, img_resize, cv::Size(1280, 720));
}
else
{
img_resize = image_reclor;
}
warpPerspective(img_resize, Transimg, TransMat, img_resize.size());
imwrite("Transimg.jpg", Transimg);
cv::waitKey(0);
return 0;
}
04
安卓端实现
private Point Ceneter = new Point(640, 512);
private float half_H = 42;
private float half_W = 280;
private float scale = (float) 0.8;
private float shift_x =100;
private float shift_y = -20;
private Mat TransMat;
private void init(){
Mat src_mat = new Mat(4,1,CvType.CV_32FC2);
Mat dst_mat = new Mat(4,1,CvType.CV_32FC2);
src_mat.put(0,0,
485, 510,
840, 425,
847, 510,
487, 567);
float new_half_H = half_H * scale;
float new_half_W = half_W * scale;
dst_mat.put(0,0,
Ceneter.x + shift_x - new_half_W, Ceneter.y + shift_y - new_half_H,
Ceneter.x + shift_x + new_half_W, Ceneter.y + shift_y - new_half_H,
Ceneter.x + shift_x + new_half_W, Ceneter.y + shift_y + new_half_H,
Ceneter.x + shift_x - new_half_W, Ceneter.y + shift_y + new_half_H);
TransMat = Imgproc.getPerspectiveTransform(src_mat, dst_mat);
}
private void prosessImg(Bitmap frame, String resultFileName){
Bitmap rgba = frame.copy(Bitmap.Config.ARGB_8888, true);
Mat handimg = new Mat();// = imread(image_path, 1);
Utils.bitmapToMat(rgba, handimg);
int Train_Channel_size_ = 3;
Mat image_reclor = new Mat();
if (handimg.channels() == 3 && Train_Channel_size_ == 1)
cvtColor(handimg, image_reclor, COLOR_BGR2GRAY);
else if (handimg.channels() == 4 && Train_Channel_size_ == 1)
cvtColor(handimg, image_reclor, COLOR_BGRA2GRAY);
else if (handimg.channels() == 4 && Train_Channel_size_ == 3)
cvtColor(handimg, image_reclor, COLOR_BGRA2BGR);
else if (handimg.channels() == 1 && Train_Channel_size_ == 3)
cvtColor(handimg, image_reclor, COLOR_GRAY2BGR);
else
image_reclor = handimg;
Mat img_resize = new Mat();
Size size = new Size(1280, 720);
if (image_reclor.size() != size) {
Imgproc.resize(image_reclor, img_resize, size);
}
else
{
img_resize = image_reclor;
}
Mat Transimg = new Mat();
Imgproc.warpPerspective(img_resize, Transimg, TransMat, img_resize.size());
rgba = PhotoUtil.matToBitmap(Transimg);
String resultPicName = resultFileName.substring(0, resultFileName.lastIndexOf(".txt"));
resultPicName = resultPicName + "_res.jpg";
FileUtil.saveBitmap(new File(resultPicName),rgba);
rgba.recycle();
rgba = null;
}
05
结果
原图
变化后图像
/ The End /
扫码关注我们
看更多嵌入式案例
喜欢本篇内容请给我们点个在看
免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!