图像变换: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*1024Point2f 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;//同7float new_half_W = half_W * scale;//同8float 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);elseimage_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);elseimage_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获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!





