Smorodov 579 Жалоба Опубликовано July 19, 2012 Наваял ресайзер на основе сплайнов Catmul-Rom, мне кажется результат выглядит лучше, чем масштабирование OpenCV-шным ресайзом, с любыми опциями. Для цвета пока не делал, работает только с серыми одноканальными. Эта функция Scale2Times удваивает исходный размер изображения. Для произвольного масштаба, можно сначала масштабировать до размера, кратного степени 2, я затем линейной интерполяцией уменьшить размер до необходимого. #include <iostream> #include <vector> #include <stdio.h> #include <stdarg.h> #include "opencv2/core/core.hpp" #include "opencv2/core/gpumat.hpp" #include "opencv2/core/opengl_interop.hpp" #include "opencv2/gpu/gpu.hpp" #include "opencv2/ml/ml.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/contrib/contrib.hpp" #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/nonfree/nonfree.hpp" #include "fstream" #include "iostream" using namespace std; using namespace cv; //----------------------------------------------------------------------------------------------------- // Catmul-rom сплайн (полно разных вариантов в инете). Catmul-rom отличается тем, что проходит через // все узловые точки, то есть, не происходит искажения существующей информации. //----------------------------------------------------------------------------------------------------- // Берем 2 точки, находим, что между p1 и p2, p0 и p3 нужны для нахождения касательных // на краях. Параметр t - меняется от 0 до 1 (0 - мы в точке p1, 1 - в точке p2) //----------------------------------------------------------------------------------------------------- void PointOnCurve(Point2f &out, float t, Point2f p0, Point2f p1, Point2f p2, Point2f p3) { float t2 = t * t; float t3 = t2 * t; out.x = 0.5f * ( ( 2.0f * p1.x ) + ( -p0.x + p2.x ) * t + ( 2.0f * p0.x - 5.0f * p1.x + 4 * p2.x - p3.x ) * t2 + ( -p0.x + 3.0f * p1.x - 3.0f * p2.x + p3.x ) * t3 ); out.y = 0.5f * ( ( 2.0f * p1.y ) + ( -p0.y + p2.y ) * t + ( 2.0f * p0.y - 5.0f * p1.y + 4 * p2.y - p3.y ) * t2 + ( -p0.y + 3.0f * p1.y - 3.0f * p2.y + p3.y ) * t3 ); } //----------------------------------------------------------------------------------------------------- // Интерполяция патча 4х4 точки // // S * S * S * S // * * * * * * * // S * S * S * S // * * * * * * * // S * S * S * S // * * * * * * * // S * S * S * S // // S- точки исходного изображения // // Вначале последовательно посчитаем два средних столбца, и найдем точки D // // S * 1 * 2 * S // * * * * * * * // S * 1 * 2 * S // * * D * D * * // S * 1 * 2 * S // * * * * * * * // S * 1 * 2 * S // // Затем последовательно посчитаем две средних строки, и найдем точки F // // S * S * S * S // * * * * * * * // 3 * 3 F 3 * 3 // * * D * D * * // 4 * 4 F 4 * 4 // * * * * * * * // S * S * S * S // // И последовательно посчитаем две диагонали, и после усреднения c учетом соседей, и найдем точку С // // 1 * S * S * 2 // * * * * * * * // S * 1 F 2 * S // * * D C D * * // S * 2 F 1 * S // * * * * * * * // 2 * S * S * 1 //----------------------------------------------------------------------------------------------------- void PointOnSurface(Mat& src,Mat& dst) { float t=0.5; Point2f out; dst=Mat(3,3,CV_32FC1); // Угловые точки результата совпадают с точками центральной ячейки исходного патча dst.at<float>(0,0)=src.at<float>(1,1); dst.at<float>(2,0)=src.at<float>(2,1); dst.at<float>(0,2)=src.at<float>(1,2); dst.at<float>(2,2)=src.at<float>(2,2); Point2f p0; Point2f p1; Point2f p2; Point2f p3; // по столбцам (2 средних) x = rows, y = value p0.x=0;p0.y=src.at<float>(0,1); p1.x=1;p1.y=src.at<float>(1,1); p2.x=2;p2.y=src.at<float>(2,1); p3.x=3;p3.y=src.at<float>(3,1); PointOnCurve(out,t,p0,p1,p2,p3); dst.at<float>(1,0)=out.y; // по столбцам (2 средних) x = rows, y = value p0.x=0;p0.y=src.at<float>(0,2); p1.x=1;p1.y=src.at<float>(1,2); p2.x=2;p2.y=src.at<float>(2,2); p3.x=3;p3.y=src.at<float>(3,2); PointOnCurve(out,t,p0,p1,p2,p3); dst.at<float>(1,2)=out.y; // по строкам (2 средних) x = cols, y = value p0.x=0;p0.y=src.at<float>(1,0); p1.x=1;p1.y=src.at<float>(1,1); p2.x=2;p2.y=src.at<float>(1,2); p3.x=3;p3.y=src.at<float>(1,3); PointOnCurve(out,t,p0,p1,p2,p3); dst.at<float>(0,1)=out.y; // по строкам (2 средних) x = cols, y = value p0.x=0;p0.y=src.at<float>(2,0); p1.x=1;p1.y=src.at<float>(2,1); p2.x=2;p2.y=src.at<float>(2,2); p3.x=3;p3.y=src.at<float>(2,3); PointOnCurve(out,t,p0,p1,p2,p3); dst.at<float>(2,1)=out.y; // Диагонали // Диагональ 1 p0.x=0;p0.y=src.at<float>(0,0); p1.x=1;p1.y=src.at<float>(1,1); p2.x=2;p2.y=src.at<float>(2,2); p3.x=3;p3.y=src.at<float>(3,3); PointOnCurve(out,t,p0,p1,p2,p3); float d1=out.y; // Диагональ 2 p0.x=0;p0.y=src.at<float>(3,0); p1.x=1;p1.y=src.at<float>(2,1); p2.x=2;p2.y=src.at<float>(1,2); p3.x=3;p3.y=src.at<float>(0,3); PointOnCurve(out,t,p0,p1,p2,p3); float d2=out.y; // Усредняем dst.at<float>(1,1)=1.0/6.0*(d1+d2+dst.at<float>(0,1)+dst.at<float>(1,0)+dst.at<float>(1,2)+dst.at<float>(2,1)); } //----------------------------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------- void Scale2Times(Mat& src_img,Mat &dstImg) { Mat imgf,img; Mat dst; Mat src; src_img.convertTo(imgf,CV_32FC1,1.0/255.0); cv::copyMakeBorder(imgf,img,1,1,1,1,cv::BORDER_REFLECT); dstImg=Mat(src_img.rows*2,src_img.cols*2,CV_32FC1); for(int i=0;i<img.rows-4;i++) { for(int j=0;j<img.cols-4;j++) { img(Rect(j,i,4,4)).copyTo(src); PointOnSurface(src,dst); dst.copyTo(dstImg(Rect(2*j+1,2*i+1,3,3))); } } dstImg=dstImg(Rect(0,0,dstImg.cols-2,dstImg.rows-2)).clone(); } //----------------------------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------------------------- int main( int argc, char** argv ) { namedWindow("Src"); namedWindow("cvResize"); namedWindow("Catmul-Rom"); Mat Img=imread("C:\\ImagesForTest\\1.tiff",0); imshow("Src",Img); Mat dstImg; Scale2Times(Img,dstImg); imshow("Catmul-Rom",dstImg); Mat ImgLin(Img.rows*2,Img.cols*2,CV_8UC1); cv::resize(Img,ImgLin,Size(Img.cols*2,Img.rows*2),INTER_CUBIC); imshow("cvResize",ImgLin); waitKey(0); //getchar(); return 0; } [/code] Catmul-Rom.cpp Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах