Jump to content
Compvision.ru
Sign in to follow this  
olkin

motion blur

Recommended Posts

Ыаыаы у меня старая версия, не читает Ваши заголовочные) обновляю

Share this post


Link to post
Share on other sites

У меня 2.4, не все заголовочные нужны,это у меня просто файл для экспериментов, там всего накидал.

Последовательное применение двух сверток по отрезку.



#include <iostream>
#include <vector>
#include <stdio.h>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cstddef>
#include "opencv2/core/core.hpp"
#include "opencv2/core/gpumat.hpp"
#include "opencv2/core/opengl_interop.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
// ---------------------------------
// src - исходное изображение
// p - точка, с которой начинается свертка
// v - направление вектора-ядра (орт вектора размытия)
// N - длина вектора размытия (ядра свертки)
// ---------------------------------
Vec3f ConvolvePoint(Mat& src,Point2f p,Vec2f v,int N)
{
Vec3f sum=0;
float k=1.0/(float)N;
for(int i=0;i<N;i++)
{
if(p.y+(float)i*v[1]>0 && p.y+(float)i*v[1]<src.rows && p.x+(float)i*v[0]>0 && p.x+(float)i*v[0]<src.cols)
{
sum+=k*src.at<Vec3f>(p.y+(float)i*v[1],p.x+(float)i*v[0]);
}
}
return sum;
}
// ---------------------------------
// Применяем размытие к изображению
// ---------------------------------
void Blur(Mat& src,Mat& dst)
{
// Углы для двух стадий размытия
float alpha1=45*CV_PI/180.0;
float alpha2=-30*CV_PI/180.0;

for(int i=0;i<src.rows;i++)
{
for(int j=0;j<src.cols;j++)
{
// Индексация матриц строка, столбец
// компоненты точки столбец, строка
// компоненты вектора столбец, строка

// последовательно, начиная от исходной точки производим свертку
// следующая свертка начинается там, где кончилась предыдущая.
// так как сумма коэффициентов каждой свертки равна 1, то результат последовательного
// применения ядер нужно разделить на количество этих ядер.

dst.at<Vec3f>(i,j)=(ConvolvePoint(src,Point2f(j,i),Vec2f(cos(alpha1),sin(alpha1)),10)+
ConvolvePoint(src,Point2f(j+10*sin(alpha1),i+10*cos(alpha1)),Vec2f(cos(alpha2),sin(alpha2)),10))/2;
}

}
}
// ---------------------------------
//
// ---------------------------------
int main( int argc, char** argv )
{
namedWindow("Image");
namedWindow("Labels");

Mat Img=imread("C:\\ImagesForTest\\skull.jpg",1);
Img.convertTo(Img,CV_32FC1,1.0/255.0);
int width=Img.cols;
int height=Img.rows;
Mat resim(Img.size(),CV_32FC3);
Blur(Img,resim);
imshow("Labels",resim);
imshow("Image",Img);
cvWaitKey(0);

}[/code]

Share this post


Link to post
Share on other sites

Делюсь впечатлениями)

Во первых, лучше никому не знать, какого года, оказывается, у меня была установлена версия OpenCV)) и насколько в 2.4.2 всё сразу легче пошло. Во вторых, огромное спасибо за код. Собственно, вот этот фрагмент

if(p.y+(float)i*v[1]>0 && p.y+(float)i*v[1]<src.rows && p.x+(float)i*v[0]>0 && p.x+(float)i*v[0]<src.cols)

                {

                        sum+=k*src.at<Vec3f>(p.y+(float)i*v[1],p.x+(float)i*v[0]);

и есть то изящное решение, на котором я стопорилась, у меня реализация выглядела несколько иначе, и в этом был основной косяк. Ну и, конечно, в той версии, немножко;) В общем, за это огромнейшее спасибо, вопрос шоколадки остался в силе. Сейчас дорабатываю всякие мелочи, в частности, там по краям рамка шириной в вектор не размывается, на Вашех скрине не видно, так как фон черный.

...А строит картинку оно у меня секунд 40, кстати. Но дело еще может быть в слабом рабочем ноуте.

На очереди сплайны, сгладить ломанную и пустить свертку уже по кривой:)

Share this post


Link to post
Share on other sites

Там надпись снизу, она размыта, может конечно с другой стороны не размывает, по картинке не видно.

Вообще, вроде бы должно размываться (цикл по всем точкам изображения идет), сейчас проверять лень.

Просто надо аккуратно проверить, что он на краях делает (может там ядро меньше, так и коэффициенты надо корректировать), ну в общем не люблю краевые эффекты,они обычно сильно программу усложняют. Хотя есть решение, которое ленивые челы, как я любят :) - это copyMakeBorder, советую посмотреть. Если кратко, то она делает поля заданной ширины вокруг изображения. Если поле сделать размером с краевой эффект, то все как бы само собой решается.

ЗЫ: Сложность алгоритма N*M*L, где N и M, ширина и высота изображения, а L количество точек в кривой свертки.

Вот и считайте.

ЗЫЗЫ: Идеальный алгоритм для распараллеливания на GPU. Раз 100 точно быстрее будет. См. CUDA.

Share this post


Link to post
Share on other sites

Тестила на белой картинке с черный контуром квадрата в центре - оно наглядней всего. Верхний и правый края стали черно-белым градиентом четко по ширине вектора. Ну может и мой косяк, код-то не дословно слизан:)

copyMakeBorder - читала где-то, спасибо за подсказку, я тоже ленивый чел;)

Хех, мне до распаралеливания еще..)

Share this post


Link to post
Share on other sites

Вроде все неплохо.

post-1-0-20110400-1344460473_thumb.jpg

В смысле так и должно быть, ведь с краю, то ничего нет, вот он и намазывает нули.

Там просто коэффициент надо корректировать, ядро уменьшается, а делит как для полного, длиной L.

Вот что я имел ввиду:

post-1-0-33383700-1344460886_thumb.jpg

#include <iostream>
#include <vector>
#include <stdio.h>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cstddef>
#include "opencv2/core/core.hpp"
#include "opencv2/core/gpumat.hpp"
#include "opencv2/core/opengl_interop.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;

Vec3f ConvolvePoint(Mat& src,Point2f p,Vec2f v)
{
Vec3f sum=0;
//float k=1.0/30.0; // По 10 точкам вектора
double L=0;
for(int i=0;i<30;i++)
{
if(p.y+(float)i*v[1]>0 && p.y+(float)i*v[1]<src.rows && p.x+(float)i*v[0]>0 && p.x+(float)i*v[0]<src.cols)
{
sum+=src.at<Vec3f>(p.y+(float)i*v[1],p.x+(float)i*v[0]);
L++;
}
}
if(L>0)
{
sum/=L;
}
return sum;
}
// ---------------------------------
//
// ---------------------------------
void Blur(Mat& src,Mat& dst)
{
for(int i=0;i<src.rows;i++)
{
for(int j=0;j<src.cols;j++)
{
dst.at<Vec3f>(i,j)=ConvolvePoint(src,Point2f(j,i),Vec2f(1,1)); // Vec2f(1,1) - вектор под 45 градусов
}

}
}
// ---------------------------------
//
// ---------------------------------
int main( int argc, char** argv )
{
namedWindow("Image");
namedWindow("Labels");

Mat Img=imread("C:\\ImagesForTest\\grid.png",1);
Img.convertTo(Img,CV_32FC1,1.0/255.0);
int width=Img.cols;
int height=Img.rows;
Mat resim(Img.size(),CV_32FC3);
Blur(Img,resim);
imshow("Labels",resim);
imshow("Image",Img);
cvWaitKey(0);

}[/code]

Share this post


Link to post
Share on other sites

Размывает не хуже чем в фотошопе, я сравнивала:) Рамка только. Походу, потому что

if(p.y+(float)i*v[1]>0 && p.y+(float)i*v[1]<src.rows && p.x+(float)i*v[0]>0 && p.x+(float)i*v[0]<src.cols)

вектор упирается в край, и там тормозит. Только, чего оно черным стало - фиг знает

ну да да. но леньки ж)

Share this post


Link to post
Share on other sites

См. вверх ^ :)

Share this post


Link to post
Share on other sites

По поводу этого топика: http://www.compvision.ru/forum/index.php?showtopic=935 чей это код (первоисточник)? его можно использовать в программе, ко мне не прийдут специально обученные дяди с вопросом про лицензию?)

Share this post


Link to post
Share on other sites

Там есть ссылка на первоисточник, ничего про лицензию там не пишут, и файлы в открытом доступе.

См. graphic gems 1 файл fitCurves.cpp и где то там же рисовалка для сплайнов. Ничего про лицензию внутри нет.

Вообще, я там достаточно много перекроил.

PS: Я еще один быстрый способ свертки совсем забыл упомянуть. Это свертка при помощи FFT. Делается так:

1) находим спектр картинки (преобразование Фурье).

2) находим спектр кривой, нарисованной на черном фоне, начинающейся из центра картинки.

3) перемножаем спектры.

4) проводим обратное преобразование Фурье.

Еще один плюс этого способа - отсутствие краевых эффектов.

Share this post


Link to post
Share on other sites

Литература? С преобразований Фурье начинала, но для начала было слишком сложно разобраться, забросила. Может и правда, так как сейчас кривую надо параметризировать, пускать точку уже не по вектору, а по кривой

Share this post


Link to post
Share on other sites

Не нужна тут литература, хватит и документации openCV.

Это все очень просто делается.

см.

dft

mulSpectrums

в opencv - шной документации.

И вот тут посмотрите (примерно на середине): http://www.fmwconcepts.com/imagemagick/fourier_transforms/fourier.html

Но тут все-же не совсем то.

О нашел: смотрите по ссылке выше подзаголовки Ideal Defocus и Ideal Motion Blur.

Эти полосатые картинки и есть Фурье спектр ядра свертки, для дефокуса - круг, для motion blur - короткая прямая.

У Вас вместо белой точки будет Ваша кривая, перемножать надо не с изображением кривой, а с ее спектром.

  • Like 1

Share this post


Link to post
Share on other sites
Еще один плюс этого способа - отсутствие краевых эффектов.

При свёртке через фурье краевые эффекы будут. Просто они будут иметь другой характер.

Share this post


Link to post
Share on other sites

Что то код с сайта плохо работает выдает только кусок изображения, не пойму где косяк.

post-1-0-51901700-1344506061_thumb.jpg

взял отсюда:

http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=mulspectrums#dft

#include <iostream>
#include <vector>
#include <stdio.h>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cstddef>
#include "opencv2/core/core.hpp"
#include "opencv2/core/gpumat.hpp"
#include "opencv2/core/opengl_interop.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;

void convolveDFT(Mat& A, Mat& B, Mat& C)
{
// reallocate the output array if needed
C.create(abs(A.rows - B.rows)+1, abs(A.cols - B.cols)+1, A.type());
Size dftSize;
// compute the size of DFT transform
dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1);
dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1);

// allocate temporary buffers and initialize them with 0's
Mat tempA(dftSize, A.type(), Scalar::all(0));
Mat tempB(dftSize, B.type(), Scalar::all(0));

// copy A and B to the top-left corners of tempA and tempB, respectively
Mat roiA(tempA, Rect(0,0,A.cols,A.rows));
A.copyTo(roiA);
Mat roiB(tempB, Rect(0,0,B.cols,B.rows));
B.copyTo(roiB);

// now transform the padded A & B in-place;
// use "nonzeroRows" hint for faster processing
dft(tempA, tempA, 0, A.rows);
dft(tempB, tempB, 0, B.rows);

// multiply the spectrums;
// the function handles packed spectrum representations well
mulSpectrums(tempA, tempB, tempA, 0);

// transform the product back from the frequency domain.
// Even though all the result rows will be non-zero,
// you need only the first C.rows of them, and thus you
// pass nonzeroRows == C.rows
dft(tempA, tempA, DFT_INVERSE + DFT_SCALE, A.rows);

// now copy the result back to C.
tempA(Rect(0, 0, C.cols, C.rows)).copyTo(C);

// all the temporary buffers will be deallocated automatically
}
// ---------------------------------
//
// ---------------------------------
int main( int argc, char** argv )
{
namedWindow("Image");
namedWindow("Kernel");
namedWindow("Result");
Mat Img=imread("C:\\ImagesForTest\\grid.png",0);
Img.convertTo(Img,CV_32FC1,1.0/255.0);
Mat kernel=imread("C:\\ImagesForTest\\Point.jpg",0);
kernel.convertTo(kernel,CV_32FC1,1.0/255.0);
int width=Img.cols;
int height=Img.rows;
Mat resim;

convolveDFT(kernel,Img, resim);

normalize(resim,resim,0,1,cv::NORM_MINMAX);
imshow("Kernel",kernel);
imshow("Image",Img);
imshow("Result",resim);
cvWaitKey(0);

}[/code]

Share this post


Link to post
Share on other sites

Поправил код, но краевые эффекты тут действительно проявляются не хуже чем при обычной обработке.

#include <iostream>
#include <vector>
#include <stdio.h>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cstddef>
#include "opencv2/core/core.hpp"
#include "opencv2/core/gpumat.hpp"
#include "opencv2/core/opengl_interop.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;

void convolveDFT(Mat& A, Mat& B, Mat& C)
{
// reallocate the output array if needed
C.create(abs(A.rows - B.rows)+1, abs(A.cols - B.cols)+1, A.type());
Size dftSize;
// compute the size of DFT transform
dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1);
dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1);

// allocate temporary buffers and initialize them with 0's
Mat tempA(dftSize, A.type(), Scalar::all(0));
Mat tempB(dftSize, B.type(), Scalar::all(0));

// copy A and B to the top-left corners of tempA and tempB, respectively

Mat roiA(tempA, Rect(0,0,A.cols,A.rows));
A.copyTo(roiA);
Mat roiB(tempB, Rect(0,0,B.cols,B.rows));
B.copyTo(roiB);

// now transform the padded A & B in-place;
// use "nonzeroRows" hint for faster processing
dft(tempA, tempA,0,A.rows);
dft(tempB, tempB,0,A.rows);

// multiply the spectrums;
// the function handles packed spectrum representations well
mulSpectrums(tempA, tempB, tempA, 0);

// transform the product back from the frequency domain.
// Even though all the result rows will be non-zero,
// you need only the first C.rows of them, and thus you
// pass nonzeroRows == C.rows
dft(tempA, tempA, DFT_INVERSE + DFT_SCALE);

// now copy the result back to C.
C=tempA(Rect((dftSize.width-A.cols)/2,(dftSize.height-A.rows)/2,A.cols,A.rows)).clone();
// all the temporary buffers will be deallocated automatically
}
// ---------------------------------
//
// ---------------------------------
int main( int argc, char** argv )
{
namedWindow("Image");
namedWindow("Kernel");
namedWindow("Result");
Mat Img=imread("C:\\ImagesForTest\\grid.png",0);
Img.convertTo(Img,CV_32FC1,1.0/255.0);
Mat kernel=imread("C:\\ImagesForTest\\Point.jpg",0);
kernel.convertTo(kernel,CV_32FC1,1.0/255.0);
int width=Img.cols;
int height=Img.rows;
Mat resim;

convolveDFT(Img,kernel, resim);

normalize(resim,resim,0,1,cv::NORM_MINMAX);
imshow("Kernel",kernel);
imshow("Image",Img);
imshow("Result",resim);
cvWaitKey(0);

}[/code]

Ядро, кстати говоря, надо центровать по центру масс, иначе изображение едет (хотя х.з. тут эксперименты нужны).

Ключевая точка (якорь) здесь середина ядра, вот от этой точки и идет размазывание. Если сместим не туда, изображение съезжает, что и понятно, т.к. в точку якоря идут значения точек находящихся на расстоянии смещения нашей кривой от якоря.

post-1-0-60619100-1344507704_thumb.jpg

Share this post


Link to post
Share on other sites

Здравствуйте опять:) Сделала по сплайну, всё красиво, краевой исправила "на коленке" - дорисовала копимейкбордером и после применения свертки - кропнула)) задача теперь новая - добавить третью координату. То есть, фактически, при z>0 картинка "едет" на нас (увеличивается на каждом шаге свертки), в обратную - уменьшается. Вопрос опять таки в алгоритме. После каждого шага свертки увеличивить\уменьшать картинку? Или существует некий Vec4f?

Share this post


Link to post
Share on other sites

Ну тут, если я правильно понял задачу, все достаточно просто.

Делаем набор изображений, по количеству равный желаемому ядру свертки, каждое из изображений увеличенное/уменьшенное и размытое по сплайну (но размер матрицы у всех одинаковый), находим взвешенную сумму (как раньше) только не между соседними пикселями одного изображения, а между пикселями с одинаковыми координатами в "стопке" изображений.

Share this post


Link to post
Share on other sites

Это самый рациональный способ? Если я правильно поняла, время рассчета задачи увеличивается катастрофически (по сплайну и так получается около 40 секунд, за что меня все время пинают)

Share this post


Link to post
Share on other sites

Никуда от этого не деться, размерность задачи увеличивается на единицу - будьте добры увеличить на единицу показатель степени количества операций .

А что Фурье то не применяете для размыва по сплайну?

PS: Это релиз работает 40 секунд?

Share this post


Link to post
Share on other sites

А я перекрутила Безье по Вашей ссылке, там всё хорошо) сам сплайн строится мгновенно, а вот скорость блюра зависит от длины кривой, количества точек аппроксимации, шага свертки... Ну и качество пропорционально времени выходит. Повторю на всякий: свертку сделать двухмерную, потом размножить картинку н раз (по длине третьей координаты), каждый раз увеличивая и кропая. И потом еще раз произвести свертку, но уже по финальных картинках?

Share this post


Link to post
Share on other sites

Дык Безье никуда не денется (кривая рисуется на ядре свертки (см.выше)), Фурье только саму свертку ускорит в количество раз пропорциональное длине ядра, для этого метода размер кривой не имеет значения.

А так, да все правильно, только уточню : последняя свертка выполняется вглубь (суммируются пиксели имеющие одинаковые координаты, но находящиеся на разных изображениях).

Share this post


Link to post
Share on other sites

Вероятно в этом (перепутал я rows и cols)

mask.create(Mag.cols,Mag.rows,CV_32F);
Упс, это я про другой код :) У Вас, скорее всего тип данных не CV_32FC1, или размеры изображений не совпадают. Посмотрите в отладчике. Это не блюр (не в том виде котором Вам нужно, хотя отличается только ядром), но можно отсюда натащить кусков:
#include "stdafx.h"
#pragma once
#include <string>
#include <iostream>
using namespace std;
using namespace cv;
//----------------------------------------------------------
// Функция для перестановки четвертей изображения местамии
// так, чтобы ноль спектра находился в центре изображения.
//----------------------------------------------------------
void Recomb(Mat &src,Mat &dst)
{
int cx = src.cols>>1;
int cy = src.rows>>1;
Mat tmp;
tmp.create(src.size(),src.type());
src(Rect(0, 0, cx, cy)).copyTo(tmp(Rect(cx, cy, cx, cy)));
src(Rect(cx, cy, cx, cy)).copyTo(tmp(Rect(0, 0, cx, cy)));
src(Rect(cx, 0, cx, cy)).copyTo(tmp(Rect(0, cy, cx, cy)));
src(Rect(0, cy, cx, cy)).copyTo(tmp(Rect(cx, 0, cx, cy)));
dst=tmp;
}
//----------------------------------------------------------
// По заданному изображению рассчитывает
// действительную и мнимую части спектра Фурье
//----------------------------------------------------------
void ForwardFFT(Mat &Src, Mat *FImg)
{
int M = getOptimalDFTSize( Src.rows );
int N = getOptimalDFTSize( Src.cols );
Mat padded;
copyMakeBorder(Src, padded, 0, M - Src.rows, 0, N - Src.cols, BORDER_CONSTANT, Scalar::all(0));
// Создаем комплексное представление изображения
// planes[0] содержит само изображение, planes[1] его мнимую часть (заполнено нулями)
Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
Mat complexImg;
merge(planes, 2, complexImg);
dft(complexImg, complexImg);
// После преобразования результат так-же состоит из действительной и мнимой части
split(complexImg, planes);

// обрежем спектр, если у него нечетное количество строк или столбцов
planes[0] = planes[0](Rect(0, 0, planes[0].cols & -2, planes[0].rows & -2));
planes[1] = planes[1](Rect(0, 0, planes[1].cols & -2, planes[1].rows & -2));

Recomb(planes[0],planes[0]);
Recomb(planes[1],planes[1]);
// Нормализуем спектр
planes[0]/=float(M*N);
planes[1]/=float(M*N);
FImg[0]=planes[0].clone();
FImg[1]=planes[1].clone();
}
//----------------------------------------------------------
// По заданным действительной и мнимой части
// спектра Фурье восстанавливает изображение
//----------------------------------------------------------
void InverseFFT(Mat *FImg,Mat &Dst)
{
Recomb(FImg[0],FImg[0]);
Recomb(FImg[1],FImg[1]);
Mat complexImg;
merge(FImg, 2, complexImg);
// Производим обратное преобразование Фурье
idft(complexImg, complexImg);
split(complexImg, FImg);
normalize(FImg[0], Dst, 0, 1, CV_MINMAX);
}
//----------------------------------------------------------
// Раскладывает изображение на амплитуду и фазу спектра Фурье
//----------------------------------------------------------
void ForwardFFT_Mag_Phase(Mat &src, Mat &Mag,Mat &Phase)
{
Mat planes[2];
ForwardFFT(src,planes);
Mag.zeros(planes[0].rows,planes[0].cols,CV_32F);
Phase.zeros(planes[0].rows,planes[0].cols,CV_32F);
cv::cartToPolar(planes[0],planes[1],Mag,Phase);
}
//----------------------------------------------------------
// По заданным амплитуде и фазе
// спектра Фурье восстанавливает изображение
//----------------------------------------------------------
void InverseFFT_Mag_Phase(Mat &Mag,Mat &Phase, Mat &dst)
{
Mat planes[2];
planes[0].create(Mag.rows,Mag.cols,CV_32F);
planes[1].create(Mag.rows,Mag.cols,CV_32F);
cv::polarToCart(Mag,Phase,planes[0],planes[1]);
InverseFFT(planes,dst);
}
//----------------------------------------------------------
// Точка входа
//----------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
// Матрица изображения
Mat img;
// Ампльтуда спектра
Mat Mag;
// Фаза спектра
Mat Phase;
// Грузим изображение
img=imread("data/lena.bmp",0);
// Покажем размеры изображения
cout<<img.size().width<<endl;
cout<<img.size().height<<endl;

// Раскладываем изображение в спектр
ForwardFFT_Mag_Phase(img,Mag,Phase);

//----------------------------------------------------------
// Частотный фильтр
//----------------------------------------------------------
// нарисуем кольцо посередине
int R=100; // Внешний радиус кольца пропускания
int r=30; // Внутренний радиус кольца пропускания
Mat mask;
mask.create(Mag.rows,Mag.cols,CV_32F);
int cx = Mag.cols>>1;
int cy = Mag.rows>>1;
mask=1;
cv::circle(mask,cv::Point(cx,cy),R,CV_RGB(0,0,0),-1);
cv::circle(mask,cv::Point(cx,cy),r,CV_RGB(1,1,1),-1);
//mask=1-mask; // Раскомментировать для инверсии
cv::multiply(Mag,mask,Mag);
cv::multiply(Phase,mask,Phase);
//----------------------------------------------------------
// Обратное преобразование
//----------------------------------------------------------
InverseFFT_Mag_Phase(Mag,Phase,img);

//----------------------------------------------------------
// Вывод результатов
//----------------------------------------------------------
// Преобразуем к виду удобному для отображения в окне
Mat LogMag;
LogMag.zeros(Mag.rows,Mag.cols,CV_32F);
LogMag=(Mag+1);
cv::log(LogMag,LogMag);
//---------------------------------------------------
imshow("Логарифм амплитуды", LogMag);
imshow("Фаза", Phase);
imshow("Результат фильтрации", img);
//----------------------------------------------------------
// Ждем нажатия кнопки
//----------------------------------------------------------
cvWaitKey(0);
return 0;
}

[/code]

Share this post


Link to post
Share on other sites

да я смотрю, что там нельзя будет разбить области видимости, точнее, прийдется разбивать на сегменты и сворачивать по их количеству, что впринципе и компенсирует выигранное время:( сижу читаю про потоки, так то всё готово, но дооолго

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×