如何使用MATLAB使黑板文本更清晰? [英] How to make the blackboard text appear clearer using MATLAB?

查看:86
本文介绍了如何使用MATLAB使黑板文本更清晰?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我希望最终图像在数字类型外观上更清晰,我应该放置什么样的滤镜序列。我的意思是只有两种不同的颜色,一种用于纸板,另一种用于粉笔书写。

解决方案

在识别图像中的文字时,最好使用






  #includemex.h
#include< vector>
#include< map>
#include< set>
#include< algorithm>
#include< math.h>
using namespace std;

#define PI 3.14159265

struct Point2d {
int x;
int y;
浮动SWT;
};

struct Point2dFloat {
float x;
浮动y;
};

struct Ray {
Point2d p;
Point2d q;
std :: vector< Point2d>点;
};


void strokeWidthTransform(const float * edgeImage,
const float * gradientX,
const float * gradientY,
bool dark_on_light,
float * SWTImage,
int h,int w,
std :: vector< Ray>& rays){
//第一次传递
float prec = .05f;
for(int row = 0; row< h; row ++){
const float * ptr = edgeImage + row * w;
for(int col = 0; col< w; col ++){
if(* ptr> 0){
Ray r;

Point2d p;
p.x = col;
p.y = row;
r.p = p;
std :: vector< Point2d>点;
points.push_back(p);

float curX =(float)col + 0.5f;
float curY =(float)row + 0.5f;
int curPixX = col;
int curPixY = row;
float G_x = gradientX [col + row * w];
float G_y = gradientY [col + row * w];
//规范化梯度
float mag = sqrt((G_x * G_x)+(G_y * G_y));
if(dark_on_light){
G_x = -G_x / mag;
G_y = -G_y / mag;
}其他{
G_x = G_x / mag;
G_y = G_y / mag;
}
while(true){
curX + = G_x * prec;
curY + = G_y * prec;
if((int)(floor(curX))!= curPixX ||(int)(floor(curY))!= curPixY){
curPixX =(int)(floor(curX));
curPixY =(int)(floor(curY));
//检查像素是否在图像外边界
if(curPixX< 0 ||(curPixX> = w)|| curPixY< 0 ||(curPixY> = h)){
休息;
}
Point2d pnew;
pnew.x = curPixX;
pnew.y = curPixY;
points.push_back(pnew);

if(edgeImage [curPixY * w + curPixX]> 0){
r.q = pnew;
//点积
浮点数G_xt = gradientX [curPixY * w + curPixX];
float G_yt = gradientY [curPixY * w + curPixX];
mag = sqrt((G_xt * G_xt)+(G_yt * G_yt));
if(dark_on_light){
G_xt = -G_xt / mag;
G_yt = -G_yt / mag;
}其他{
G_xt = G_xt / mag;
G_yt = G_yt / mag;
}

if(acos(G_x * -G_xt + G_y * -G_yt)< PI / 2.0){
float length = sqrt(((float)rqx - ( float)rpx)*((float)rqx - (float)rpx)+((float)rqy - (float)rpy)*((float)rqy - (float)rpy));
for(std :: vector< Point2d> :: iterator pit = points.begin(); pit!= points.end(); pit ++){
float * pSWT = SWTImage + w * pit- > y + pit-> x;
if(* pSWT< 0){
* pSWT = length;
} else {
* pSWT = std :: min(length,* pSWT);
}
}
r.points = points;
rays.push_back(r);
}
休息;
}
}
}
}
ptr ++;
}
}
}


bool Point2dSort(const Point2d& lhs,const Point2d& rhs){
return lhs。 SWT< rhs.SWT;
}

void SWTMedianFilter(float * SWTImage,int h,int w,
std :: vector< Ray>& rays,float maxWidth = -1){
for(std :: vector< Ray> :: iterator rit = rays.begin(); rit!= rays.end(); rit ++){
for(std :: vector< Point2d> :: iterator pit = rit-> points.begin(); pit!= rit-> points.end(); pit ++){
pit-> SWT = SWTImage [w * pit-> y + pit- > x];
}
std :: sort(rit-> points.begin(),rit-> points.end(),& Point2dSort);
// std :: nth_element(rit-> points.begin(),rit-> points.end(),rit-> points.size()/ 2,& Point2dSort);
浮点数中位数=(rit-> points [rit-> points.size()/ 2])。SWT;
if(maxWidth> 0&& median> = maxWidth){
median = -1;
}
for(std :: vector< Point2d> :: iterator pit = rit-> points.begin(); pit!= rit-> points.end(); pit ++){
SWTImage [w * pit-> y + pit-> x] = std :: min(pit-> SWT,median);
}
}
}

typedef std :: vector<的std ::设置< INT> > graph_t; //图形作为每个节点的邻居列表

void connComp(const graph_t& g,std :: vector< int>& c,int i,int l){
//从节点开始i labe这个conn-comp与标签l
if(i< 0 || i> g.size()){
return;
}
std :: vector< int>栈;
// push i
stack.push_back(i);
c [i] = l;
while(!stack.empty()){
// pop
i = stack.back();
stack.pop_back();
//遍历所有nieghbors
for(std :: set< int> :: const_iterator it = g [i] .begin(); it!= g [i] .end(); it ++ ){
if(c [* it]< 0){
stack.push_back(* it);
c [* it] = l;
}
}
}
}
int findNextToLabel(const graph_t& g,const vector< int>& c){
for(int i = 0; i< c.size(); i ++){
if(c [i]< 0){
return i;
}
}
返回c.size();
}

int connected_components(const graph_t& g,vector< int>& c){
//检查空图!
if(g.empty()){
返回0;
}
int i = 0;
int num_conn = 0;
do {
connComp(g,c,i,num_conn);
num_conn ++;
i = findNextToLabel(g,c);
} while(i< g.size());
返回num_conn;
}

std :: vector<的std ::矢量<&的Point2D GT; >
findLegallyConnectedComponents(const float * SWTImage,int h,int w,
std :: vector< Ray>& rays){
std :: map< int,int>地图;
std :: map< int,Point2d> revmap;
std :: vector< std :: vector< Point2d> >组件; //空
int num_vertices = 0,idx = 0;
graph_t g;
//图表的数字顶点。将每个点与数字
相关联(int row = 0; row< h; row ++){
for(int col = 0; col< w; col ++){
idx = col + w *行;
if(SWTImage [idx]> 0){
Map [idx] = num_vertices;
Point2d p;
p.x = col;
p.y = row;
revmap [num_vertices] = p;
num_vertices ++;
std :: set< int>空;
g.push_back(空);
}
}
}
if(g.empty()){
返回组件; //与空图无关...
}
for(int row = 0; row< h; row ++){
for(int col = 0; col< w; col ++){
idx = col + w * row;
if(SWTImage [idx]> 0){
//检查右边的像素,右下,下,左下来
int this_pixel = Map [idx];
float thisVal = SWTImage [idx];
if(col + 1< w){
float right = SWTImage [w * row + col + 1];
if(右> 0&&(thisVal / right< = 3.0 || right / thisVal< = 3.0)){
g [this_pixel] .insert(Map [w * row + col + 1]);
g [Map [w * row + col + 1]] .insert(this_pixel);
// boost :: add_edge(this_pixel,map.at(row * SWTImage-> width + col + 1),g);
}
}
if(row + 1< h){
if(col + 1< w){
float right_down = SWTImage [w *( row + 1)+ col + 1];
if(right_down> 0&&(thisVal / right_down< = 3.0 || right_down / thisVal< = 3.0)){
g [this_pixel] .insert(Map [w *(row) +1)+ col + 1]);
g [Map [w *(row + 1)+ col + 1]] .insert(this_pixel);
// boost :: add_edge(this_pixel,map.at((row + 1)* SWTImage-> width + col + 1),g);
}
}
浮动= SWTImage [w *(row + 1)+ col];
if(向下> 0&&(thisVal / down< = 3.0 || down / thisVal< = 3.0)){
g [this_pixel] .insert(Map [w *(row) +1)+ col]);
g [Map [w *(row + 1)+ col]] .insert(this_pixel);
// boost :: add_edge(this_pixel,map.at((row + 1)* SWTImage-> width + col),g);
}
if(col-1> = 0){
float left_down = SWTImage [w *(row + 1)+ col - 1];
if(left_down> 0&&(thisVal / left_down< = 3.0 || left_down / thisVal< = 3.0)){
g [this_pixel] .insert(Map [w *(row) +1)+ col - 1]);
g [Map [w *(row + 1)+ col - 1]] .insert(this_pixel);
// boost :: add_edge(this_pixel,map.at((row + 1)* SWTImage-> width + col - 1),g);
}
}
}
}
}
}

std :: vector< int> c(num_vertices,-1);
int num_comp = connected_components(g,c);

components.reserve(num_comp);
// std :: cout<< 在过滤之前,<< num_comp<< 组件和<< num_vertices<< 顶点<<的std :: ENDL;
for(int j = 0; j< num_comp; j ++){
std :: vector< Point2d> TMP;
components.push_back(tmp);
}
for(int j = 0; j< num_vertices; j ++){
Point2d p = revmap [j];
(components [c [j]])。push_back(p);
}

返回组件;
}

enum {
EIN = 0,
GXIN,
GYIN,
DOLFIN,
MAXWIN,
NIN};

void mexFunction(int nout,mxArray * pout [],int nin,const mxArray * pin []){
//
//确保图像以转置方式输入因此它们在内存中排列为主要内容
//
mxAssert(nin == NIN,错误的输入数);
mxAssert(nout> 1,只有一个输出);

int h = mxGetN(pin [EIN]); //输入被转置!
int w = mxGetM(pin [EIN]);

mxAssert(mxIsClass(pin [EIN],mxSINGLE_CLASS)&& h == mxGetN(pin [EIN])&& w == mxGetM(pin [EIN]),edge地图不正确);
mxAssert(mxIsClass(pin [GXIN],mxSINGLE_CLASS)&& h == mxGetN(pin [GXIN])&& w == mxGetM(pin [GXIN]),edge map wrong) ;
mxAssert(mxIsClass(pin [GYIN],mxSINGLE_CLASS)&& h == mxGetN(pin [GYIN])&& w == mxGetM(pin [GYIN]),edge map wrong) ;

const float * edgeImage =(float *)mxGetData(pin [EIN]);
const float * gradientX =(float *)mxGetData(pin [GXIN]);
const float * gradientY =(float *)mxGetData(pin [GYIN]);

bool dark_on_light = mxGetScalar(pin [DOLFIN])!= 0;
float maxWidth = mxGetScalar(pin [MAXWIN]);

//分配输出
pout [0] = mxCreateNumericMatrix(w,h,mxSINGLE_CLASS,mxREAL);
float * SWTImage =(float *)mxGetData(pout [0]);
//将SWT设置为-1
for(int i = 0; i< w * h; i ++){
SWTImage [i] = -1;
}

std :: vector< Ray>射线;
strokeWidthTransform(edgeImage,gradientX,gradientY,dark_on_light,SWTImage,h,w,rays);
SWTMedianFilter(SWTImage,h,w,rays,maxWidth);

//连接组件
if(nout> 1){
//从SWT和渐变图像计算合法连接组件。
//返回类型是向量的向量,其中每个外部向量是一个组件,
//内部向量包含该组件中每个像素的(y,x)。
std :: vector< std :: vector< Point2d> > components = findLegallyConnectedComponents(SWTImage,h,w,rays);
pout [1] = mxCreateNumericMatrix(w,h,mxSINGLE_CLASS,mxREAL);
float * pComp =(float *)mxGetData(pout [1]);
for(int i = 0; i< w * h; i ++){
pComp [i] = 0;
}
for(int ci = 0; ci< components.size(); ci ++){
for(std :: vector< Point2d> :: iterator it = components [ci] .begin(); it!= components [ci] .end(); it ++){
pComp [w * it-> y + it-> x] = ci + 1;
}
}
}
}






matlab函数调用stroke-width-transform(SWT)mex-file:

  function [swt swtcc] = SWT(img,dol,maxWidth)

if size(img,3)== 3
img = rgb2gray(img);
结束
img = im2single(img);

edgeMap = single(edge(img,'canny',。15));
img = imfilter(img,fspecial('gauss',[5 5],0.3 *(2.5-1)+。8));
gx = imfilter(img,fspecial('prewitt')'); %//'
gy = imfilter(img,fspecial('prewitt'));
gx = single(medfilt2(gx,[3 3]));
gy = single(medfilt2(gy,[3 3]));

[swt swtcc] = swt_mex(edgeMap。',gx。',gy。',dol,maxWidth); %//'

swt = swt'; %//'
swtcc = double(swtcc'); %//'


What are the sequence of filters I should put if I want the final image to be more clearer with a digital type look. I mean only two distinct colors, one for the board and one for the chalk writing.

解决方案

When it comes to identifying text in images you better use Stroke Width Transform.

Here's a little result I obtained on your image (the basic transform + connected component w/o filtering):

My mex implementation based on code from here


#include "mex.h"
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <math.h>
using namespace std;

#define PI 3.14159265

struct Point2d {
    int x;
    int y;
    float SWT;
};

struct Point2dFloat {
    float x;
    float y;
};

struct Ray {
    Point2d p;
    Point2d q;
    std::vector<Point2d> points;
};


void strokeWidthTransform(const float * edgeImage,
    const float * gradientX,
    const float * gradientY,
    bool dark_on_light,
    float * SWTImage,
    int h, int w,
    std::vector<Ray> & rays) {
    // First pass
    float prec = .05f;
    for( int row = 0; row < h; row++ ){
        const float* ptr = edgeImage + row*w;        
        for ( int col = 0; col < w; col++ ){
            if (*ptr > 0) {
                Ray r;

                Point2d p;
                p.x = col;
                p.y = row;
                r.p = p;
                std::vector<Point2d> points;
                points.push_back(p);

                float curX = (float)col + 0.5f;
                float curY = (float)row + 0.5f;
                int curPixX = col;
                int curPixY = row;
                float G_x = gradientX[ col + row*w ];                        
                float G_y = gradientY[ col + row*w ];
                // normalize gradient
                float mag = sqrt( (G_x * G_x) + (G_y * G_y) );
                if (dark_on_light){
                    G_x = -G_x/mag;
                    G_y = -G_y/mag;
                } else {
                    G_x = G_x/mag;
                    G_y = G_y/mag;                    
                }
                while (true) {
                    curX += G_x*prec;
                    curY += G_y*prec;
                    if ((int)(floor(curX)) != curPixX || (int)(floor(curY)) != curPixY)     {    
                        curPixX = (int)(floor(curX));
                        curPixY = (int)(floor(curY));
                        // check if pixel is outside boundary of image
                        if (curPixX < 0 || (curPixX >= w) || curPixY < 0 || (curPixY >= h)) {    
                            break;
                        }
                        Point2d pnew;
                        pnew.x = curPixX;
                        pnew.y = curPixY;
                        points.push_back(pnew);

                        if ( edgeImage[ curPixY*w+ curPixX ] > 0) {
                            r.q = pnew;
                            // dot product
                            float G_xt = gradientX[ curPixY*w + curPixX ];
                            float G_yt = gradientY[ curPixY*w + curPixX ];
                            mag = sqrt( (G_xt * G_xt) + (G_yt * G_yt) );
                            if (dark_on_light){
                                G_xt = -G_xt/mag;
                                G_yt = -G_yt/mag;
                            } else {
                                G_xt = G_xt/mag;
                                G_yt = G_yt/mag;                                
                            }

                            if (acos(G_x * -G_xt + G_y * -G_yt) < PI/2.0 ) {
                                float length = sqrt( ((float)r.q.x - (float)r.p.x)*((float)r.q.x - (float)r.p.x) + ((float)r.q.y - (float)r.p.y)*((float)r.q.y - (float)r.p.y));
                                for (std::vector<Point2d>::iterator pit = points.begin(); pit != points.end(); pit++) {
                                    float* pSWT = SWTImage +  w * pit->y + pit->x;
                                    if (*pSWT < 0) {
                                        *pSWT = length;
                                    } else {
                                        *pSWT = std::min(length, *pSWT);
                                    }
                                }
                                r.points = points;
                                rays.push_back(r);
                            }
                            break;
                        }
                    }
                }
            }
            ptr++;
        }
    }    
}


bool Point2dSort(const Point2d &lhs, const Point2d &rhs) {
    return lhs.SWT < rhs.SWT;
}

void SWTMedianFilter(float * SWTImage, int h, int w,
        std::vector<Ray> & rays, float maxWidth = -1 ) {
    for (std::vector<Ray>::iterator rit = rays.begin(); rit != rays.end(); rit++) {
        for (std::vector<Point2d>::iterator pit = rit->points.begin(); pit != rit->points.end(); pit++) {
            pit->SWT = SWTImage[ w*pit->y + pit->x ];
        }
        std::sort(rit->points.begin(), rit->points.end(), &Point2dSort);
        //std::nth_element( rit->points.begin(), rit->points.end(), rit->points.size()/2, &Point2dSort );
        float median = (rit->points[rit->points.size()/2]).SWT;
        if ( maxWidth > 0 && median >= maxWidth ) {
            median = -1;
        }
        for (std::vector<Point2d>::iterator pit = rit->points.begin(); pit != rit->points.end(); pit++) {
            SWTImage[ w*pit->y + pit->x ] = std::min(pit->SWT, median);
        }
    }    
}

typedef std::vector< std::set<int> > graph_t; // graph as a list of neighbors per node

void connComp( const graph_t& g, std::vector<int>& c, int i, int l ) {
    // starting from node i labe this conn-comp with label l
    if ( i < 0 || i > g.size() ) {
        return;
    }
    std::vector< int > stack;
    // push i
    stack.push_back(i);
    c[i] = l;
    while ( ! stack.empty() ) {
        // pop
        i = stack.back();
        stack.pop_back();
        // go over all nieghbors
        for ( std::set<int>::const_iterator it = g[i].begin(); it != g[i].end(); it++ ) {
            if ( c[*it] < 0 ) {
                stack.push_back( *it );
                c[ *it ] = l;
            }
        }
    }
}
int findNextToLabel( const graph_t& g, const vector<int>& c ) {
    for ( int i = 0 ; i < c.size(); i++ ) {
        if ( c[i] < 0 ) {
            return i;
        }
    }
    return c.size();
}

int connected_components(const graph_t& g, vector<int>& c) {
    // check for empty graph!
    if ( g.empty() ) {
        return 0;
    }
    int i = 0;
    int num_conn = 0;
    do {
        connComp( g, c, i, num_conn );
        num_conn++;
        i = findNextToLabel( g, c );
    } while ( i < g.size() );
    return num_conn;
}

std::vector< std::vector<Point2d> >
        findLegallyConnectedComponents(const float* SWTImage, int h, int w,
        std::vector<Ray> & rays) {
    std::map<int, int> Map;
    std::map<int, Point2d> revmap;
    std::vector<std::vector<Point2d> > components; // empty
    int num_vertices = 0, idx = 0;
    graph_t g;
    // Number vertices for graph.  Associate each point with number
    for( int row = 0; row < h; row++ ){        
        for (int col = 0; col < w; col++ ){
            idx = col + w * row;
            if (SWTImage[idx] > 0) {
                Map[idx] = num_vertices;
                Point2d p;
                p.x = col;
                p.y = row;
                revmap[num_vertices] = p;
                num_vertices++;
                std::set<int> empty;
                g.push_back(empty);
            }
        }
    }   
    if ( g.empty() ) {
        return components; // nothing to do with an empty graph...
    }
    for( int row = 0; row < h; row++ ){        
        for (int col = 0; col < w; col++ ){
            idx = col + w * row;
            if ( SWTImage[idx] > 0) {
                // check pixel to the right, right-down, down, left-down
                int this_pixel = Map[idx];
                float thisVal = SWTImage[idx];
                if (col+1 < w) {
                    float right = SWTImage[ w*row + col + 1 ];
                    if (right > 0 && (thisVal/right <= 3.0 || right/thisVal <= 3.0)) {
                        g[this_pixel].insert( Map[ w*row + col + 1 ] );                    
                        g[ Map[ w*row + col + 1 ] ].insert( this_pixel );
                        //boost::add_edge(this_pixel, map.at(row * SWTImage->width + col + 1), g);
                    }
                }
                if (row+1 < h) {
                    if (col+1 < w) {
                        float right_down = SWTImage[ w*(row+1) + col + 1 ];
                        if (right_down > 0 && (thisVal/right_down <= 3.0 || right_down/thisVal <= 3.0)) {
                            g[ this_pixel ].insert( Map[ w*(row+1) + col + 1 ] );
                            g[ Map[ w*(row+1) + col + 1 ] ].insert(this_pixel);                            
                            // boost::add_edge(this_pixel, map.at((row+1) * SWTImage->width + col + 1), g);
                        }
                    }
                    float down = SWTImage[ w*(row+1) + col ];
                    if (down > 0 && (thisVal/down <= 3.0 || down/thisVal <= 3.0)) {
                        g[ this_pixel ].insert( Map[ w*(row+1) + col ] );
                        g[ Map[ w*(row+1) + col ] ].insert( this_pixel );
                        //boost::add_edge(this_pixel, map.at((row+1) * SWTImage->width + col), g);
                    }
                    if (col-1 >= 0) {
                        float left_down = SWTImage[ w*(row+1) + col - 1 ];
                        if (left_down > 0 && (thisVal/left_down <= 3.0 || left_down/thisVal <= 3.0)) {
                            g[ this_pixel ].insert( Map[ w*(row+1) + col - 1 ] );
                            g[ Map[ w*(row+1) + col - 1 ] ].insert( this_pixel );
                            //boost::add_edge(this_pixel, map.at((row+1) * SWTImage->width + col - 1), g);
                        }
                    }
                }    
            }            
        }
    }

    std::vector<int> c(num_vertices, -1);    
    int num_comp = connected_components(g, c);    

    components.reserve(num_comp);
    //std::cout << "Before filtering, " << num_comp << " components and " <<     num_vertices << " vertices" << std::endl;
    for (int j = 0; j < num_comp; j++) {
        std::vector<Point2d> tmp;
        components.push_back( tmp );
    }
    for (int j = 0; j < num_vertices; j++) {
        Point2d p = revmap[j];
        (components[c[j]]).push_back(p);
    }

    return components;
}

enum {
    EIN = 0,
    GXIN,
    GYIN,
    DOLFIN,
    MAXWIN,
    NIN };

void mexFunction( int nout, mxArray* pout[], int nin, const mxArray* pin[] ) {
    //    
    // make sure images are input in transposed so that they are arranged row-major in memory
    //
    mxAssert( nin == NIN, "wrong number of inputs" );
    mxAssert( nout > 1, "only one output" );

    int h = mxGetN( pin[EIN] ); // inputs are transposed!
    int w = mxGetM( pin[EIN] );

    mxAssert( mxIsClass( pin[EIN], mxSINGLE_CLASS ) && h == mxGetN( pin[EIN] ) && w == mxGetM( pin[EIN] ), "edge map incorrect");
    mxAssert( mxIsClass( pin[GXIN], mxSINGLE_CLASS ) && h == mxGetN( pin[GXIN] ) && w == mxGetM( pin[GXIN] ), "edge map incorrect");
    mxAssert( mxIsClass( pin[GYIN], mxSINGLE_CLASS ) && h == mxGetN( pin[GYIN] ) && w == mxGetM( pin[GYIN] ), "edge map incorrect");

    const float * edgeImage = (float*) mxGetData( pin[EIN] );
    const float * gradientX = (float*) mxGetData( pin[GXIN] );
    const float * gradientY = (float*) mxGetData( pin[GYIN] );

    bool dark_on_light = mxGetScalar( pin[DOLFIN] ) != 0 ;
    float maxWidth = mxGetScalar( pin[MAXWIN] );

    // allocate output
    pout[0] = mxCreateNumericMatrix( w, h, mxSINGLE_CLASS, mxREAL );
    float * SWTImage = (float*) mxGetData( pout[0] );
    // set SWT to -1
    for ( int i = 0 ; i < w*h; i++ ) {
        SWTImage[i] = -1;
    }

    std::vector<Ray> rays;
    strokeWidthTransform ( edgeImage, gradientX, gradientY, dark_on_light, SWTImage, h, w, rays );
    SWTMedianFilter ( SWTImage, h, w, rays, maxWidth );

    // connected components
    if ( nout > 1 ) {
        // Calculate legally connect components from SWT and gradient image.
        // return type is a vector of vectors, where each outer vector is a component and
        // the inner vector contains the (y,x) of each pixel in that component.
        std::vector<std::vector<Point2d> > components = findLegallyConnectedComponents(SWTImage, h, w, rays);
        pout[1] = mxCreateNumericMatrix( w, h, mxSINGLE_CLASS, mxREAL );
        float* pComp = (float*) mxGetData( pout[1] );
        for ( int i = 0 ; i < w*h; i++ ) {
            pComp[i] = 0;
        }
        for ( int ci = 0 ; ci < components.size(); ci++ ) {
            for ( std::vector<Point2d>::iterator it = components[ci].begin() ; it != components[ci].end(); it++ ) {
                pComp[ w * it->y + it->x ] = ci + 1;
            }
        }
    }
}


Matlab function calling stroke-width-transform (SWT) mex-file:

function [swt swtcc] = SWT( img, dol, maxWidth )

if size( img, 3 ) == 3
    img = rgb2gray(img);
end
img = im2single(img);

edgeMap = single( edge( img, 'canny', .15 ) ); 
img = imfilter( img, fspecial('gauss',[5 5], 0.3*(2.5-1)+.8) );
gx = imfilter( img, fspecial('prewitt')' ); %//'
gy = imfilter( img, fspecial('prewitt') );
gx = single(medfilt2( gx, [3 3] ));
gy = single(medfilt2( gy, [3 3] ));

[swt swtcc] = swt_mex( edgeMap.', gx.', gy.', dol, maxWidth ); %//'

swt = swt'; %//'
swtcc = double(swtcc'); %//'

这篇关于如何使用MATLAB使黑板文本更清晰?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆