Baixe o app para aproveitar ainda mais
Prévia do material em texto
Reamostragem A reamostragem de imagens é amplamente utilizada em processamento de imagens e vídeos. Ela é utilizada para ampliar, reduzir, e rotacionar imagens. Também é utilizada para criar efei- tos como “morphing/warping”, para corrigir distorção da lente, para fazer interpolação de co- res nos dispositivos para aquisição de imagens (câmeras, scanners,etc), para registrar imagens (criar uma única imagem “grudando” duas ou mais imagens), gerar imagens em coordenadas especiais como log-polar, estabilizar tremor da câmera de vídeo, para corrigir a movimenta- ção do paciente em imagens médicas, para normalizar imagens médicas que envolvem vários sujeitos, etc. Os métodos populares para reamostragem de imagens incluem: • Vizinho mais próximo • Bilinear • Bicúbico • Spline • Reamostragem Lanczos Os programas abaixo fazem ampliação/redução de imagens usando interpolação vizinho mais próximo: // vizinho.cpp pos-2016 #include <cekeikon.h> int main(int argc, char** argv) { if (argc!=4) { printf("vizinho ent.pgm sai.pgm fator\n"); erro("Erro: Numero de argumentos invalido"); } Mat_<GRY> a; le(a,argv[1]); double fator; sscanf(argv[3],"%lf",&fator); int nl=int(a.rows*fator); int nc=int(a.cols*fator); Mat_<GRY> b(nl,nc); for (int l=0; l<b.rows; l++) for (int c=0; c<b.cols; c++) b(l,c) = a(cvRound(l/fator),cvRound(c/fator)); imp(b,argv[2]); } //vizinho.cpp - pos-2012 #include <cekeikon.h> int main() { Mat_<GRY> ent; le(ent,"lennag.tga"); Mat_<GRY> sai(600,600); // cria sai for (int l=0; l<sai.rows; l++) for (int c=0; c<sai.cols; c++) { int le = round(l * ((ent.rows-1.0)/(sai.rows-1.0))); int ce = round(c * ((ent.cols-1.0)/(sai.cols-1.0))); sai(l,c) = ent(le, ce); } imp(sai,"vizinho.tga"); } // camzoom.cpp grad-2014 modificado // Muda fator de zoom ao longo do tempo. #include <cekeikon.h> Mat_<GRY> amplia(Mat_<GRY> b, double fator) { Mat_<GRY> d(round(b.rows*fator),round(b.cols*fator)); for (int l=0; l<d.rows; l++) for (int c=0; c<d.cols; c++) d(l,c) = b( round(l/fator), round(c/fator) ); return d; } int main() { VideoCapture vi(0); vi.set(CV_CAP_PROP_FRAME_WIDTH,640); vi.set(CV_CAP_PROP_FRAME_HEIGHT,480); if (!vi.isOpened()) erro("Erro abertura webcam"); Mat_<COR> a; Mat_<GRY> b; int ch; namedWindow("janela"); double dt=M_PI/90; double t=0; do { vi >> a; flip(a,a,1); converte(a,b); b=amplia(b, 1+0.5*sin(t)); t+=dt; imshow("janela",b); ch=waitKey(1); } while (ch!=27); } // cvvizinho.cpp pos2012 - usa funcao resize do OpenCV //vizinho.cpp #include <cekeikon.h> int main() { Mat_<GRY> ent; le(ent,"lennag.tga"); Mat_<GRY> sai; resize(ent, sai, Size(600,600), 0, 0, INTER_NEAREST); imp(sai,"cvvizinho.tga"); } //INTER_NEAREST nearest-neighbor interpolation //INTER_LINEAR bilinear interpolation (used by default) //INTER_AREA resampling using pixel area relation. It may be the 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_CUBIC bicubic interpolation over 4x4 pixel neighborhood //INTER_LANCZOS4 Lanczos interpolation over 8x8 pixel neighborhood Os programas abaixo fazem ampliação de imagens usando interpolação bilinear: //linear.cpp pos2016 #include <cekeikon.h> int main() { Mat_<GRY> a; le(a,"lenna.jpg"); Mat_<GRY> b(600,600); // cria b for (int l=0; l<b.rows; l++) for (int c=0; c<b.cols; c++) { double ald = l * ((a.rows-1.0)/(b.rows-1.0)); double acd = c * ((a.cols-1.0)/(b.cols-1.0)); int fal=int(ald); int fac=int(acd); double dl=ald-fal; double dc=acd-fac; double p1=(1-dl)*(1-dc); double p2=(1-dl)*dc; double p3=dl*(1-dc); double p4=dl*dc; b(l,c) = round( p1*a(fal,fac) + p2*a(fal,fac+1) + p3*a(fal+1,fac) + p4*a(fal+1,fac+1) ); } imp(b,"linear.pgm"); } //cvlinear.cpp pos2012 interpolacao linear usando resize // do OpenCV #include <cekeikon.h> int main() { Mat_<GRY> ent; le(ent,"lennag.tga"); Mat_<GRY> sai; resize(ent, sai, Size(600,600), 0, 0, INTER_LINEAR); imp(sai,"cvlinear.tga"); } Abaixo, a imagem lennag.tga com 512×512 pixels foi reamostrada para 600×700 pixels usan- do interpolações vizinho mais próximo e bilinear: vizinho mais próximo bilinear Abaixo, a imagem lennag.tga com 512×512 pixels foi aumentada 320% usando as interpola- ções do programa Jasc Paint Shop Pro e Alchemy: vizinho mais próximo bilinear bicúbico lanczos3 (sinc) Existem situações em que é preferível acessar uma imagem fornecendo coordenadas (x, y), em vez de coordenadas (l, c). Efetuar uma rotação de uma imagem é uma destas situações. Seria muito conveniente se pudesse definir o pixel central da imagem, e se pudesse acessar os pi- xels da imagem fornecendo coordenadas (x, y). A biblioteca Cekeikon permite este tipo de acesso, através do modo atC (centralizado com background), atX (estendido) e atR (replicado). Veja o programa abaixo: //coordxy.cpp #include <cekeikon.h> int main() { // Mat_<GRY> t=(Mat_<GRY>(3,3) << 1,2,3, // 4,5,6, // 7,8,9); // ImgXyb<GRY> a=t; ImgXyb<GRY> a=(ImgXyb<GRY>)(Mat_<GRY>(3,3) << 1,2,3, 4,5,6, 7,8,9); a.centro(1,1); a.backg=255; printf("a(-1,-1)=%d\n",a(-1,-1)); printf("a(-1,+1)=%d\n",a(-1,+1)); printf("minx=%d maxx=%d miny=%d maxy=%d\n", a.minx, a.maxx, a.miny, a.maxy); printf("a(-2,-1)=%d\n",a(-2,-1)); } Saída: a(-1,-1)=7 a(-1,+1)=1 minx=-1 maxx=1 miny=-1 maxy=1 a(-2,-1)=255 Neste programa, foi criada uma imagem 3×3, e o pixel central foi definido como o centro da imagem através do comando a.centro(1,1); Daí em diante, a(-1,-1) irá acessar o pixel a(x,y)=a(-1,-1). A variável a.minx devolve o menor valor da coordenada x do domínio da imagem, isto é, -1. As funções a.maxx,a.miny,a.maxy são análogos. Se acessar um pixel fora do domínio da imagem, acessa-se o pixel a.backg. A fórmula da rotação é: )cos(θ=c )sen(θ=s − = cs sc yxyx vvnn ],[],[ − = cs sc yxyx nnvv ],[],[ onde θ é o ângulo da rotação, [xv, yv] são as coordenadas de um pixel antes da rotação e [xv, yv] são as suas coordenadas após a rotação. Usando coordenadas [l,c], a fórmula não muda: − = cs sc clcl vvnn ],[],[ Também pode-se escrever o mesmo como (notação usada no OpenCV): − = v v n n y x cs sc y x − = n n v v y x cs sc y x x y l c x y Os seguintes programas efetuam uma rotação na imagem, usando interpolação vizinho mais próximo. //rotacao.cpp pos2016 #include <cekeikon.h> int main(int argc, char** argv) { if (argc!=4) { printf("rotacao ent.pgm sai.pgm graus\n"); erro("Erro: Numero de argumentos invalido"); } double graus; sscanf(argv[3],"%lf",&graus);double radianos=deg2rad(graus); double co=cos(radianos); double se=sin(radianos); ImgXyb<GRY> a; le(a,argv[1]); //a.centro(a.rows/2,a.cols/2); a.backg=255; a.centro(); a.backg=255; ImgXyb<GRY> b(a.rows,a.cols); b.centro(); b.backg=255; for (int xn=b.minx; xn<=b.maxx; xn++) for (int yn=b.miny; yn<=b.maxy; yn++) { int xv=round(xn*co+yn*se); int yv=round(-xn*se+yn*co); b(xn,yn)=a(xv,yv); } imp(b,argv[2]); } // rotacao_cv.cpp pos2016 #include <cekeikon.h> int main() { Mat_<GRY> ent; le(ent,"lenna.jpg"); //mostra(ent); Mat_<GRY> sai; Mat_<double> m=getRotationMatrix2D(Point2f(ent.cols/2,ent.rows/2), 30, 1); cout << m << endl; warpAffine(ent, sai, m, ent.size(), INTER_LINEAR, BORDER_CONSTANT, Scalar(255)); mostra(sai); } [0.8660254037844387, 0.4999999999999999, -93.70250336881629; -0.4999999999999999, 0.8660254037844387, 162.2974966311837] //camrot.cpp grad-2014 modificado #include <cekeikon.h> Mat_<GRY> rotacao(Mat_<GRY> ap, double angrad) { Mat_<GRY> bp(ap.rows,ap.cols); IMG_<GRY> a(ap); a.backg=255; IMG_<GRY> b(bp); double c=cos(angrad); double s=sin(angrad); for (int x=b.minx; x<=b.maxx; x++) for (int y=b.miny; y<b.maxy; y++) { double xv=x*c+y*s; double yv=-x*s+y*c; b.atC(x,y) = a.atR(round(xv),round(yv)); } return bp; } int main() { VideoCapture vi(0); vi.set(CV_CAP_PROP_FRAME_WIDTH,640); vi.set(CV_CAP_PROP_FRAME_HEIGHT,480); if (!vi.isOpened()) erro("Erro abertura webcam"); Mat_<COR> a; Mat_<GRY> b; int ch; namedWindow("janela"); double t=0; do { vi >> a; flip(a,a,1); converte(a,b); b=rotacao(b,deg2rad(t)); t=t+1; imshow("janela",b); ch=waitKey(1); } while (ch!=27); } Referências: [1] William K. Pratt, “Digital Image Processing,” 2nd ed., John Wiley & Sons, 1991. Escrever programa que faz warping Explicar direito interpolação sinc (mudar amostragem 40 kHz para 44 kHz). Explicar interpolação bicúbica Nota: Suponha um senoide de 450 Hz amostrado a 1000 amostras/segundo. Não parece se- nóide. Teoricamente, é possível reconstruir. Como fazer? imagem original imagem log-polar
Compartilhar