Here is my result: For image:
I've got result:
The code:
#include <stdio.h>
#include <stdarg.h>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
namedWindow("source");
namedWindow("result");
namedWindow("ang");
Mat img=imread("D:\\ImagesForTest\\binarized_image.png",0);
cv::threshold(img,img,128,255,cv::THRESH_BINARY);
Mat thinned;
thinned=img.clone(); // Just clone the input
//Thinning(img,thinned); // Not actually needed
cv::GaussianBlur(thinned,thinned,Size(3,3),1.0);
Mat gx,gy,ang,mag;
cv::Sobel(thinned,gx,CV_32FC1,1,0);
cv::Sobel(thinned,gy,CV_32FC1,0,1);
cv::phase(gx,gy,ang,false);
cv::magnitude(gx,gy,mag);
cv::normalize(mag,mag,0,1,cv::NORM_MINMAX);
Mat angRes=Mat::zeros(img.rows*3,img.cols*3,CV_8UC1);
for (int i=0;i< img.rows;i+=2)
{
for (int j=0;j< img.cols;j+=2)
{
int x=j*3;
int y=i*3;
float r=5;
float m=r*(mag.at<float>(i,j));
float dx=m*r*cos(ang.at<float>(i,j));
float dy=m*r*sin(ang.at<float>(i,j));
cv::line(angRes,cv::Point(x,y),cv::Point(x+dx,y+dy),Scalar::all(255),1,CV_AA);
}
}
imshow("ang",angRes);
imshow("source",img);
imshow("result",thinned);
cv::waitKey(0);
}
Enother variant (weighted block averages):
#include <stdio.h>
#include <stdarg.h>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
float GetWeightedAngle(Mat& mag,Mat& ang)
{
float res=0;
float n=0;
for (int i=0;i< mag.rows;++i)
{
for (int j=0;j< mag.cols;++j)
{
res+=ang.at<float>(i,j)*mag.at<float>(i,j);
n+=mag.at<float>(i,j);
}
}
res/=n;
return res;
}
int main(int argc, char* argv[])
{
namedWindow("source");
namedWindow("ang");
Mat img=imread("D:\\ImagesForTest\\binarized_image.png",0);
cv::threshold(img,img,128,255,cv::THRESH_BINARY);
Mat thinned;
thinned=img.clone();
//Thinning(img,thinned);
//cv::GaussianBlur(thinned,thinned,Size(3,3),1.0);
Mat gx,gy,ang,mag;
cv::Sobel(thinned,gx,CV_32FC1,1,0,7);
cv::Sobel(thinned,gy,CV_32FC1,0,1,7);
cv::phase(gx,gy,ang,false);
cv::magnitude(gx,gy,mag);
cv::normalize(mag,mag,0,1,cv::NORM_MINMAX);
Mat angRes=Mat::zeros(img.rows,img.cols,CV_8UC1);
int blockSize=img.cols/15-1;
float r=blockSize;
for (int i=0;i< img.rows-blockSize;i+= blockSize)
{
for (int j=0;j< img.cols-blockSize;j+= blockSize)
{
float a=GetWeightedAngle(mag(Rect(j,i,blockSize,blockSize)),ang(Rect(j,i,blockSize,blockSize)));
float dx=r*cos(a);
float dy=r*sin(a);
int x=j;
int y=i;
cv::line(angRes,cv::Point(x,y),cv::Point(x+dx,y+dy),Scalar::all(255),1,CV_AA);
}
}
imshow("ang",angRes);
imshow("source",img);
cv::waitKey(0);
}
It gives the result image: