Opencv(C++)實現二階線性插值
阿新 • • 發佈:2018-04-01
i++ -- alt key ++ enc 新的 round idt
#include<opencv2\opencv.hpp> #include<iostream> using namespace cv; using namespace std; bool enlargedImage(Mat &src, float k1, float k2);//k1,k2表示放大的倍數 void main() { Mat srcImage = imread("flower.png"); float k1 = 1.2, k2 = 2.5; enlargedImage(srcImage, k1, k2); } bool enlargedImage(Mat &src, float k1, float k2) { int height, width, theight, twidth; int ia, ja;//新的坐標 height = src.rows;//圖像的高 width = src.cols;//圖像的寬 theight = round(height*k1);//擴大後圖像的高 cout << theight << endl; twidth = round(width*k2);//擴大後圖像的寬 cout << twidth << endl; Mat dstImage(theight, twidth, src.type(), Scalar(0)); //對得到的新圖片進行填充 for (int i = 0; i < height; i++) { for (int j = 0; j < width - 1; j++) { ia = round(i*k1); ja = round(j*k2); //如果位於四個頂角 if (ia == 0 && ja == 0)//左頂角 { dstImage.at<Vec3b>(ia, ja)[0] = src.at<Vec3b>(i, j)[0]; dstImage.at<Vec3b>(ia, ja)[1] = src.at<Vec3b>(i, j)[1]; dstImage.at<Vec3b>(ia, ja)[2] = src.at<Vec3b>(i, j)[2]; } else if (ia == theight - 1 && ja == twidth - 1)//左下角 { dstImage.at<Vec3b>(ia, ja)[0] = src.at<Vec3b>(i, j)[0]; dstImage.at<Vec3b>(ia, ja)[1] = src.at<Vec3b>(i, j)[1]; dstImage.at<Vec3b>(ia, ja)[2] = src.at<Vec3b>(i, j)[2]; } else if (ia == 0 && ja == twidth - 1)//右頂角 { dstImage.at<Vec3b>(ia, ja)[0] = src.at<Vec3b>(i, j)[0]; dstImage.at<Vec3b>(ia, ja)[1] = src.at<Vec3b>(i, j)[1]; dstImage.at<Vec3b>(ia, ja)[2] = src.at<Vec3b>(i, j)[2]; } else if (ia == theight - 1 && ja == twidth - 1)//右下角 { dstImage.at<Vec3b>(ia, ja)[0] = src.at<Vec3b>(i, j)[0]; dstImage.at<Vec3b>(ia, ja)[1] = src.at<Vec3b>(i, j)[1]; dstImage.at<Vec3b>(ia, ja)[2] = src.at<Vec3b>(i, j)[2]; } else if (ja == twidth - 1)//第三種情況,最右邊 { dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[0] = src.at<Vec3b>(i, j)[0]; dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[1] = src.at<Vec3b>(i, j)[1]; dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[2] = src.at<Vec3b>(i, j)[2]; } else if (ia == 0)//第一種情況,最上面 { dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[0] = src.at<Vec3b>(i, j)[0]; dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[1] = src.at<Vec3b>(i, j)[1]; dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[2] = src.at<Vec3b>(i, j)[2]; } else if (ja == 0)//第二種情況,最左邊 { dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[0] = src.at<Vec3b>(i, j)[0]; dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[1] = src.at<Vec3b>(i, j)[1]; dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja)[2] = src.at<Vec3b>(i, j)[2]; } else if (ia == theight - 1)//第四種情況,最下面 { dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[0] = src.at<Vec3b>(i, j)[0]; dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[1] = src.at<Vec3b>(i, j)[1]; dstImage.at<Vec3b>(ia, round((j - 1)*k2) + 1)[2] = src.at<Vec3b>(i, j)[2]; } //最後一種情況,位於中間的,將值賦給左上角的值 else { dstImage.at<Vec3b>(round((i - 1)*k1) + 1, round((j - 1)*k2) + 1)[0] = src.at<Vec3b>(i, j)[0]; dstImage.at<Vec3b>(round((i - 1)*k1) + 1, round((j - 1)*k2) + 1)[1] = src.at<Vec3b>(i, j)[1]; dstImage.at<Vec3b>(round((i - 1)*k1) + 1, round((j - 1)*k2) + 1)[2] = src.at<Vec3b>(i, j)[2]; } } } for (int i = 0; i < height; i++) { //單獨考慮最右邊 int j = width - 1; ia = round(i*k1); ja = round(j*k2); dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja + 1)[0] = src.at<Vec3b>(i, j)[0]; dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja + 1)[1] = src.at<Vec3b>(i, j)[1]; dstImage.at<Vec3b>(round((i - 1)*k1) + 1, ja + 1)[2] = src.at<Vec3b>(i, j)[2]; } int a1, a2, b1, b2;//用來表示單線性插值中的上下左右中不為0的坐標 //利用單線性進行了行插值 for (int i = 0; i < theight; i++) { for (int j = 0; j < twidth; j++) { //首先考慮的滿足單線性插值的 if (dstImage.at<Vec3b>(i, 0)[0] == 0 && dstImage.at<Vec3b>(i, 0)[1] == 0 && dstImage.at<Vec3b>(i, 0)[2] == 0) { continue; } if (dstImage.at<Vec3b>(i, j)[0] == 0 && dstImage.at<Vec3b>(i, j)[1] == 0 && dstImage.at<Vec3b>(i, j)[2] == 0&& j>0 && j < twidth) { b1 = j - 1; b2 = j + 1; while (dstImage.at<Vec3b>(i, b1)[0] == 0 && dstImage.at<Vec3b>(i, b1)[1] == 0 && dstImage.at<Vec3b>(i, b1)[2] == 0 && b1 >= 0) { b1--; } while (dstImage.at<Vec3b>(i, b2)[0] == 0 && dstImage.at<Vec3b>(i, b2)[1] == 0 && dstImage.at<Vec3b>(i, b2)[2] == 0 && b2 <twidth) { b2++; } int sfrg0 = floor(((j - b1)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b2)[0] + ((b2 - j)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b1)[0]); int sfrg1 = floor(((j - b1)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b2)[1] + ((b2 - j)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b1)[1]); int sfrg2 = floor(((j - b1)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b2)[2] + ((b2 - j)*1.0 / (b2 - b1))*dstImage.at<Vec3b>(i, b1)[2]); dstImage.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(sfrg0); dstImage.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(sfrg1); dstImage.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(sfrg2); } } } //利用單線性對列進行插值 for (int j = 0; j < twidth; j++) { for (int i = 0; i < theight; i++) { if (dstImage.at<Vec3b>(i, j)[0] == 0 && dstImage.at<Vec3b>(i, j)[1] == 0 && dstImage.at<Vec3b>(i, j)[2] == 0 && i>0 && i < theight) { a1 = i - 1; a2 = i + 1; while (dstImage.at<Vec3b>(a1, j)[0] == 0 && dstImage.at<Vec3b>(a1, j)[1] == 0 && dstImage.at<Vec3b>(a1, j)[2] == 0 && a1 >= 0) { a1--; } while (dstImage.at<Vec3b>(a2, j)[0] == 0 && dstImage.at<Vec3b>(a2, j)[1] == 0 && dstImage.at<Vec3b>(a2, j)[2] == 0 && a2 < twidth) { a2++; } int s0 = floor(((i - a1)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a2, j)[0] + ((a2 - i)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a1, j)[0]); int s1 = floor(((i - a1)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a2, j)[1] + ((a2 - i)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a1, j)[1]); int s2 = floor(((i - a1)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a2, j)[2] + ((a2 - i)*1.0 / (a2 - a1))*dstImage.at<Vec3b>(a1, j)[2]); dstImage.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(s0); dstImage.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(s1); dstImage.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(s2); } } } imshow("原圖", src); //namedWindow("擴大後的圖像", CV_WINDOW_NORMAL); imshow("擴大後的圖像", dstImage); waitKey(0); return true; }
效果圖:
Opencv(C++)實現二階線性插值