CV_EXPORTS_W Mat imread( const String& filename,int flags = IMREAD_COLOR );enumImreadModes { IMREAD_UNCHANGED =-1,//!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). Ignore EXIF orientation. IMREAD_GRAYSCALE =0,//!< If set, always convert image to the single channel grayscale image (codec internal conversion). IMREAD_COLOR =1,//!< If set, always convert image to the 3 channel BGR color image. IMREAD_ANYDEPTH =2,//!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. IMREAD_ANYCOLOR =4,//!< If set, the image is read in any possible color format. IMREAD_LOAD_GDAL =8,//!< If set, use the gdal driver for loading the image. IMREAD_REDUCED_GRAYSCALE_2 =16,//!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2. IMREAD_REDUCED_COLOR_2 =17,//!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2. IMREAD_REDUCED_GRAYSCALE_4 =32,//!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4. IMREAD_REDUCED_COLOR_4 =33,//!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4. IMREAD_REDUCED_GRAYSCALE_8 =64,//!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8. IMREAD_REDUCED_COLOR_8 =65,//!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8. IMREAD_IGNORE_ORIENTATION =128//!< If set, do not rotate the image according to EXIF's orientation flag. };
enumInterpolationFlags{ /** nearest neighbor interpolation */ INTER_NEAREST =0, /** bilinear interpolation */ INTER_LINEAR =1, /** bicubic interpolation */ INTER_CUBIC =2, /** resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire'-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method. */ INTER_AREA =3, /** Lanczos interpolation over 8x8 neighborhood */ INTER_LANCZOS4 =4, /** Bit exact bilinear interpolation */ INTER_LINEAR_EXACT =5, /** Bit exact nearest neighbor interpolation. This will produce same results as the nearest neighbor method in PIL, scikit-image or Matlab. */ INTER_NEAREST_EXACT =6, /** mask for interpolation codes */ INTER_MAX =7, /** flag, fills all of the destination image pixels. If some of them correspond to outliers in the source image, they are set to zero */ WARP_FILL_OUTLIERS =8, /** flag, inverse transformation For example, #linearPolar or #logPolar transforms: - flag is __not__ set: \f$dst( \rho , \phi ) = src(x,y)\f$ - flag is set: \f$dst(x,y) = src( \rho , \phi )\f$ */ WARP_INVERSE_MAP =16};
inlineMat Mat::operator()( constRect& roi ) const{returnMat(*this, roi);}
以下为实例
Mat xuenai =imread("xuenai.jpg");resize(xuenai,xuenai,Size(1000,1000));imshow("xuenai", xuenai);Mattuanzi(xuenai,(Rect(0,0,500,1000)));imshow("tuanzi",tuanzi);waitKey();
3.13.2 方式二
Mat::Mat(const Mat& m,const Rect& roi);
以下为实例
Mat xuenai =imread("xuenai.jpg");resize(xuenai,xuenai,Size(1000,1000));imshow("xuenai", xuenai);Mattuanzi(xuenai(Rect(0,0,500,1000)));imshow("tuanzi",tuanzi);waitKey();
Mat xuenai =imread("xuenai.jpg");imshow("xuenai",xuenai);double M_values[]={1,0,200,0,1,200};MatM(Size(3,2),CV_64F,M_values);Matxuenai_shift(xuenai.size(),xuenai.type());warpAffine(xuenai,xuenai_shift,M,xuenai.size());imshow("xuenai_shift",xuenai_shift);waitKet();
Mat xuenai =imread("xuenai.jpg");imshow("xuenai", xuenai);Mat M=getRotationMatrix2D(Point2f(xuenai.cols/2,xuenai.rows/2),45,1);Matxuenai_rotate(xuenai.size(),xuenai.type());warpAffine(xuenai,xuenai_rotate,M,xuenai.size());imshow("xuenai_flip",xuenai_rotate);
3.15.4 仿射(不破坏几何关系)
获得变换矩阵M
CV_EXPORTS Mat getAffineTransform( const Point2f src[],const Point2f dst[] );
参数如下
三个点要一一对应
3.16 透射变换(破坏几何关系)
3.16.1 API
进行变换
CV_EXPORTS_W void warpPerspective( InputArray src, OutputArray dst,
InputArray M, Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
参数如下
已知变换后图片,逆推变换矩阵M
CV_EXPORTS_W Mat getPerspectiveTransform(InputArray src, InputArray dst, int solveMethod = DECOMP_LU);
参数如下
获得变换矩阵M
CV_EXPORTS Mat getPerspectiveTransform(const Point2f src[], const Point2f dst[], int solveMethod = DECOMP_LU);
参数如下
四个点要一一对应
3.16.2 效果
Mat origin = imread("origin.jpg");
Point2f point2F_origin[4]={Point2f (405,105),Point2f(2469,217),Point2f(2573,3489),Point2f(349,3547)};
Point2f point2F_tansform[4]={Point2f (0,0),Point2f(2500,0),Point2f(2500,3500),Point2f(0,3500)};
Mat M=getPerspectiveTransform(point2F_origin,point2F_tansform);
Mat transfrom(origin.size(),origin.type());
warpPerspective(origin,transfrom,M,Size(2500,3500));
resize(origin,origin,Size(500,700));
resize(transfrom,transfrom,Size(500,700));
imshow("origin",origin);
imshow("transform",transfrom);
4.滤波及边缘检测
4.1 均值滤波
4.1.1 卷积核形状
Mat kernal=Mat::ones(Size(ksize,ksize),CV_64F)/(ksize*ksize);
4.1.2 API
CV_EXPORTS_W void blur( InputArray src, OutputArray dst,
Size ksize, Point anchor = Point(-1,-1),
int borderType = BORDER_DEFAULT );
参数如下
4.1.3 效果
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat xuenai_blur(xuenai.size(),xuenai.type());
blur(xuenai,xuenai_blur,Size(3,5));
imshow("xuenai_blur",xuenai_blur);
waitKet();
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat xuenai_Gauss(xuenai.size(),xuenai.type());
GaussianBlur(xuenai,xuenai_Gauss,Size(-1,-1),10);
imshow("xuenai_Gauss",xuenai_Gauss);
waitKet();
4.3 中值滤波
4.3.1 原理
取滤波器内的中值作为输出,可以很好的抑制椒盐噪声
4.3.2 API
CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );
参数如下
4.3.3 效果
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat xuenai_median(xuenai.size(),xuenai.type());
medianBlur(xuenai,xuenai_median,5);
imshow("xuenai_median",xuenai_median);
waitKet();
CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d,
double sigmaColor, double sigmaSpace,
int borderType = BORDER_DEFAULT );
参数如下
4.4.3 效果
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat xuenai_bilateral(xuenai.size(),xuenai.type());
bilateralFilter(xuenai,xuenai_bilateral,-1,100,10);
imshow("xuenai_bilateral",xuenai_bilateral);
waitKet();
4.5 获取用来形态学操作的滤波器
CV_EXPORTS_W Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));
enum MorphShapes {
MORPH_RECT = 0, //!< a rectangular structuring element: \f[E_{ij}=1\f]
MORPH_CROSS = 1, //!< a cross-shaped structuring element:
//!< \f[E_{ij} = \begin{cases} 1 & \texttt{if } {i=\texttt{anchor.y } {or } {j=\texttt{anchor.x}}} \\0 & \texttt{otherwise} \end{cases}\f]
MORPH_ELLIPSE = 2 //!< an elliptic structuring element, that is, a filled ellipse inscribed
//!< into the rectangle Rect(0, 0, esize.width, 0.esize.height)
};
shape:滤波器形状
ksize(kernal size):滤波器大小
anchor:滤波器中心像素位置,取(-1,-1)表示几何中心
4.6 腐蚀和膨胀(对二值图)
4.6.1 原理
腐蚀:取滤波器内的最小值作为输出
膨胀:取滤波器内的最大值作为输出
4.6.2 腐蚀API
CV_EXPORTS_W void erode( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
参数如下
4.6.3 效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_erode(xuenai.size(),xuenai.type());
erode(xuenai_threshold,xuenai_erode,kernal);
imshow("xuenai_erode",xuenai_erode);
waitKet();
4.6.4 膨胀API
CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
参数如下
4.6.5 效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_dilate(xuenai.size(),xuenai.type());
dilate(xuenai_threshold,xuenai_dilate,kernal);
imshow("xuenai_dilate",xuenai_dilate);
waitKet();
4.7 形态学操作(对二值图)
4.7.1 API
CV_EXPORTS_W void morphologyEx( InputArray src, OutputArray dst,
int op, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_morphology(xuenai.size(),xuenai.type());
morphologyEx(xuenai_threshold,xuenai_morphology,MORPH_OPEN,kernal);
imshow("xuenai_morphology",xuenai_morphology);
waitKet();
4.7.4 闭
原理
对输入图片先进行膨胀,然后进行腐蚀。可以用来屏蔽与滤波器大小相当的暗部。
效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_morphology(xuenai.size(),xuenai.type());
morphologyEx(xuenai_threshold,xuenai_morphology,MORPH_CLOSE,kernal);
imshow("xuenai_morphology",xuenai_morphology);
waitKet();
4.7.5 顶帽
原理
对输入图片先进行开操作,然后原图-开操作图。可以用来提取与滤波器大小相当的亮部。
效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_morphology(xuenai.size(),xuenai.type());
morphologyEx(xuenai_threshold,xuenai_morphology,MORPH_TOPHAT,kernal);
imshow("xuenai_morphology",xuenai_morphology);
waitKet();
4.7.6 黑帽
原理
对输入图片先进行闭操作,然后闭操作图-原图。可以用来提取与滤波器大小相当的暗部。
效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_morphology(xuenai.size(),xuenai.type());
morphologyEx(xuenai_threshold,xuenai_morphology,MORPH_BLACKHAT,kernal);
imshow("xuenai_morphology",xuenai_morphology);
waitKet();
4.7.7 形态学梯度
原理
膨胀图与腐蚀图之差。可以用来 提取边界轮廓 ,但提取效果比不上专业的边缘检测算法。
效果
Mat xuenai = imread("xuenai.jpg");
Mat xuenai_gray(xuenai.size(),xuenai.type());
cvtColor(xuenai,xuenai_gray,COLOR_BGR2GRAY);
Mat xuenai_threshold(xuenai.size(),xuenai.type());
threshold(xuenai_gray,xuenai_threshold,100,255,THRESH_BINARY);
imshow("xuenai_threshold",xuenai_threshold);
Mat kernal=getStructuringElement(MORPH_RECT,Size(3,3));
Mat xuenai_morphology(xuenai.size(),xuenai.type());
morphologyEx(xuenai_threshold,xuenai_morphology,MORPH_GRADIENT,kernal);
imshow("xuenai_morphology",xuenai_morphology);
waitKet();
enum NormTypes {
NORM_INF = 1,
NORM_L1 = 2,
NORM_L2 = 4,
NORM_L2SQR = 5,
NORM_HAMMING = 6,
NORM_HAMMING2 = 7,
NORM_TYPE_MASK = 7, //!< bit-mask which can be used to separate norm type from norm flags
NORM_RELATIVE = 8, //!< flag
NORM_MINMAX = 32 //!< flag
};
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat xuenai_canny(xuenai.size(),xuenai.type());
Canny(xuenai,xuenai_canny,60,150);
imshow("xuenai_canny",xuenai_canny);
waitKet();
4.13 添加噪声
为了检测算法的稳定性,常常需要在图片中人为地添加一些噪声来进行检验。
4.13.1 椒盐噪声
static void addSaltNoise(const Mat& src,Mat& dst,int num=1000)
{
dst=src.clone();
for (int k = 0; k < num; k++)
{
//随机取值行列,得到像素点(i,j)
int i = rand() % dst.rows;
int j = rand() % dst.cols;
//修改像素点(i,j)的像素值
for(int channel=0;channel<src.channels();channel++){
dst.ptr(i,j)[channel]=255;
}
}
for (int k = 0; k < num; k++)
{
//随机取值行列
default_random_engine engine;
uniform_int_distribution<unsigned>u(0,10000);
int i = rand() % dst.rows;
int j = rand() % dst.cols;
//修改像素点(i,j)的像素值
for(int channel=0;channel<src.channels();channel++){
dst.ptr(i,j)[channel]=0;
}
}
return;
}
void RNG::fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange = false );
参数如下
5.画几何图形
5.1 直线
5.1.1 API
CV_EXPORTS_W void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color,int thickness = 1, int lineType = LINE_8, int shift = 0);
参数如下
5.1.2 连通类型
enum LineTypes {
FILLED = -1,
LINE_4 = 4, //!< 4-connected line
LINE_8 = 8, //!< 8-connected line
LINE_AA = 16 //!< antialiased line
};
LINE_4与LINE_8差别不大,而LINE_AA的抗锯齿效果显著
5.2 正矩形
5.2.1API
CV_EXPORTS_W void rectangle(InputOutputArray img, Point pt1, Point pt2,
const Scalar& color, int thickness = 1,
int lineType = LINE_8, int shift = 0);
参数如下
CV_EXPORTS_W void rectangle(InputOutputArray img, Rect rec,
const Scalar& color, int thickness = 1,
int lineType = LINE_8, int shift = 0);
参数如下
5.3 圆形
5.3.1 API
CV_EXPORTS_W void circle(InputOutputArray img, Point center, int radius,
const Scalar& color, int thickness = 1,
int lineType = LINE_8, int shift = 0);
参数如下
5.4 椭圆
5.4.1 API
CV_EXPORTS_W void ellipse(InputOutputArray img, Point center, Size axes,
double angle, double startAngle, double endAngle,
const Scalar& color, int thickness = 1,
int lineType = LINE_8, int shift = 0);
参数如下
5.4.2 效果
Mat canvas(Size(1000,1000),CV_8U,Scalar(255));
ellipse(canvas,Point2f(500,500),Size(50,100),0,0,90,Scalar(0,0,0),5);
imshow("canvas",canvas);
waitKey();
Mat canvas(Size(1000,1000),CV_8U,Scalar(255));
ellipse(canvas,Point2f(500,500),Size(50,100),20,0,360,Scalar(0,0,0),5);
imshow("canvas",canvas);
waitKey();
Mat canvas(Size(1000,1000),CV_8U,Scalar(255));
ellipse(canvas,Point2f(500,500),Size(50,100),20,0,180,Scalar(0,0,0),5);
imshow("canvas",canvas);
waitKey();
5.5 斜矩形
5.5.1 API(通过RotatedRect类和line函数实现)
class CV_EXPORTS RotatedRect
{
public:
//! default constructor
RotatedRect();
/*center:质心坐标
size:(x方向上全边长,y方向上全边长)
angle:顺时针偏角
*/
RotatedRect(const Point2f& center, const Size2f& size, float angle);
/**
三点确定一矩形,记得要互相垂直
*/
RotatedRect(const Point2f& point1, const Point2f& point2, const Point2f& point3);
/** 返回四个角点坐标,要用Point2f类型的数组对象作为参数传入,不能是仅仅是Point类型的数组对象*/
void points(Point2f pts[]) const;
//! returns the minimal up-right integer rectangle containing the rotated rectangle
Rect boundingRect() const;
//! returns the minimal (exact) floating point rectangle containing the rotated rectangle, not intended for use with images
Rect_<float> boundingRect2f() const;
//! returns the rectangle mass center
Point2f center;
//! returns width and height of the rectangle
Size2f size;
//! returns the rotation angle. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle.
float angle;
};
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
namedWindow("xuenai_rotate");
Mat xuenai_rotate(xuenai.size(), xuenai.type());
createTrackbar("angle","xuenai_rotate", nullptr,360);
while (1) {
int angle= getTrackbarPos("angle","xuenai_rotate");
Mat M = getRotationMatrix2D(Point2f(xuenai.cols / 2, xuenai.rows / 2), angle, 1);
warpAffine(xuenai, xuenai_rotate, M, xuenai.size());
imshow("xuenai_rotate",xuenai_rotate);
waitKey(20);
}
Mat xuenai = imread("xuenai.jpg");
imshow("xuenai",xuenai);
Mat templ= imread("xuenai_rect.jpg");
imshow("template",templ);
Mat match_result;
matchTemplate(xuenai,templ,match_result,TM_SQDIFF);
Point temLoc;
Point minLoc;
Point maxLoc;
double min,max;
minMaxLoc(match_result,&min,&max,&minLoc,&maxLoc);
temLoc=minLoc;
rectangle(xuenai,Rect(temLoc.x,temLoc.y,templ.cols,templ.rows),Scalar(0,0,255));
imshow("xuenai_match",xuenai);
waitKey();
8.1.5 模板匹配的缺陷
无法应对旋转
Mat xuenai = imread("xuenai.jpg");
rotate(xuenai,xuenai,ROTATE_90_CLOCKWISE);
imshow("xuenai",xuenai);
Mat templ= imread("xuenai_rect.jpg");
Mat match_result;
matchTemplate(xuenai,templ,match_result,TM_SQDIFF);
Point temLoc;
Point minLoc;
Point maxLoc;
double min,max;
minMaxLoc(match_result,&min,&max,&minLoc,&maxLoc);
temLoc=minLoc;
rectangle(xuenai,Rect(temLoc.x,temLoc.y,templ.cols,templ.rows),Scalar(0,0,255));
imshow("xuenai_match",xuenai);
waitKey();
无法应对缩放
Mat xuenai = imread("xuenai.jpg");
resize(xuenai,xuenai,Size(500,500));
imshow("xuenai",xuenai);
Mat templ= imread("xuenai_rect.jpg");
Mat match_result;
matchTemplate(xuenai,templ,match_result,TM_SQDIFF);
Point temLoc;
Point minLoc;
Point maxLoc;
double min,max;
minMaxLoc(match_result,&min,&max,&minLoc,&maxLoc);
temLoc=minLoc;
rectangle(xuenai,Rect(temLoc.x,temLoc.y,templ.cols,templ.rows),Scalar(0,0,255));
imshow("xuenai_match",xuenai);
waitKey();
CV_EXPORTS_W void drawKeypoints( InputArray image, const std::vector<KeyPoint>& keypoints, InputOutputArray outImage,
const Scalar& color=Scalar::all(-1), DrawMatchesFlags flags=DrawMatchesFlags::DEFAULT );
enum struct DrawMatchesFlags
{
DEFAULT = 0, //!< Output image matrix will be created (Mat::create),
//!< i.e. existing memory of output image may be reused.
//!< Two source image, matches and single keypoints will be drawn.
//!< For each keypoint only the center point will be drawn (without
//!< the circle around keypoint with keypoint size and orientation).
DRAW_OVER_OUTIMG = 1, //!< Output image matrix will not be created (Mat::create).
//!< Matches will be drawn on existing content of output image.
NOT_DRAW_SINGLE_POINTS = 2, //!< Single keypoints will not be drawn.
DRAW_RICH_KEYPOINTS = 4 //!< For each keypoint the circle around keypoint with keypoint size and
//!< orientation will be drawn.
};
CV_WRAP static Ptr<FastFeatureDetector> create( int threshold=10,
bool nonmaxSuppression=true,
FastFeatureDetector::DetectorType type=FastFeatureDetector::TYPE_9_16 );
CV_WRAP static Ptr<ORB> create(int nfeatures=500, float scaleFactor=1.2f, int nlevels=8, int edgeThreshold=31,
int firstLevel=0, int WTA_K=2, ORB::ScoreType scoreType=ORB::HARRIS_SCORE, int patchSize=31, int fastThreshold=20);