V-X*_*eme 6 iphone ocr objective-c
我正在使用tesseract在我的项目中进行OCR.我使用的是72 dpi的图像.但它给出的输出远非准确性.我在某处读到,输入200 dpi以上是好的.但是tesseract库的标准图像配置是什么,即尺寸,dpi,文件格式等?
由于字符限制,这是我答案的第二部分。
这是.mm
.米
/*
* Image.cpp
* ImageProcessing
*
*
*
*/
#include "Image.h"
#include <stack>
@implementation ImageWrapper
@synthesize image;
@synthesize ownsImage;
+ (ImageWrapper *) imageWithCPPImage:(Image *) theImage;
{
ImageWrapper *wrapper = [[ImageWrapper alloc] init];
wrapper.image=theImage;
wrapper.ownsImage=true;
return [wrapper autorelease];
}
+ (ImageWrapper *) imageWithCPPImage:(Image *) theImage ownsImage:(bool) ownsTheImage;
{
ImageWrapper *wrapper = [[ImageWrapper alloc] init];
wrapper.image=theImage;
wrapper.ownsImage=ownsTheImage;
return [wrapper autorelease];
}
- (void) dealloc
{
// delete the image that we have been holding onto
if(ownsImage) delete image;
[super dealloc];
}
@end
void Image::initYptrs() {
m_yptrs=(uint8_t **) malloc(sizeof(uint8_t *)*m_height);
for(int i=0; i<m_height; i++) {
m_yptrs[i]=m_imageData+i*m_width;
}
}
Image::Image(ImageWrapper *other, int x1, int y1, int x2, int y2) {
m_width=x2-x1;
m_height=y2-y1;
m_imageData=(uint8_t *) malloc(m_width*m_height);
initYptrs();
Image *otherImage=other.image;
for(int y=y1; y<y2; y++) {
for(int x=x1; x<x2; x++) {
(*this)[y-y1][x-x1]=(*otherImage)[y][x];
}
}
m_ownsData=true;
}
Image::Image(int width, int height) {
m_imageData=(uint8_t *) malloc(width*height);
m_width=width;
m_height=height;
m_ownsData=true;
initYptrs();
}
// create an image from data
Image::Image(uint8_t *imageData, int width, int height, bool ownsData) {
m_imageData=imageData;
m_width=width;
m_height=height;
m_ownsData=ownsData;
initYptrs();
}
Image::Image(UIImage *srcImage, int width, int height, CGInterpolationQuality interpolation, bool imageIsRotatedBy90degrees) {
if(imageIsRotatedBy90degrees) {
int tmp=width;
width=height;
height=tmp;
}
m_width=width;
m_height=height;
// get hold of the image bytes
m_imageData=(uint8_t *) malloc(m_width*m_height);
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceGray();
CGContextRef context=CGBitmapContextCreate(m_imageData, m_width, m_height, 8, m_width, colorSpace, kCGImageAlphaNone);
CGContextSetInterpolationQuality(context, interpolation);
CGContextSetShouldAntialias(context, NO);
CGContextDrawImage(context, CGRectMake(0,0, m_width, m_height), [srcImage CGImage]);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
if(imageIsRotatedBy90degrees) {
uint8_t *tmpImage=(uint8_t *) malloc(m_width*m_height);
for(int y=0; y<m_height; y++) {
for(int x=0; x<m_width; x++) {
tmpImage[x*m_height+y]=m_imageData[(m_height-y-1)*m_width+x];
}
}
int tmp=m_width;
m_width=m_height;
m_height=tmp;
free(m_imageData);
m_imageData=tmpImage;
}
initYptrs();
}
void Image::normalise() {
int min=INT_MAX;
int max=0;
for(int i=0; i<m_width*m_height; i++) {
if(m_imageData[i]>max) max=m_imageData[i];
if(m_imageData[i]<min) min=m_imageData[i];
}
for(int i=0; i<m_width*m_height; i++) {
m_imageData[i]=255*(m_imageData[i]-min)/(max-min);
}
}
// copy a section of another image
ImageWrapper *Image::createImage(ImageWrapper *other, int x1, int y1, int x2, int y2)
{
return [ImageWrapper imageWithCPPImage:new Image(other, x1, y1, x2, y2)];
}
// create an empty image of the required width and height
ImageWrapper *Image::createImage(int width, int height) {
return [ImageWrapper imageWithCPPImage:new Image(width, height)];
}
// create an image from data
ImageWrapper *Image::createImage(uint8_t *imageData, int width, int height, bool ownsData) {
return [ImageWrapper imageWithCPPImage:new Image(imageData, width, height, ownsData)];
}
// take a source UIImage and convert it to greyscale
ImageWrapper *Image::createImage(UIImage *srcImage, int width, int height, bool imageIsRotatedBy90degrees) {
return [ImageWrapper imageWithCPPImage:new Image(srcImage, width, height, kCGInterpolationHigh, imageIsRotatedBy90degrees)];
}
void Image::extractConnectedRegion(int x, int y, std::vector<ImagePoint> *points) {
(*points).push_back(ImagePoint(x,y));
(*this)[y][x]=0;
int left, right;
left=x-1;
right=x+1;
while(left>=0 && (*this)[y][left]!=0) {
(*this)[y][left]=0;
(*points).push_back(ImagePoint(left,y));
left--;
}
while(right<m_width && (*this)[y][right]!=0) {
(*this)[y][right]=0;
(*points).push_back(ImagePoint(right,y));
right++;
}
for(int i=left; i<=right; i++) {
if(i>=0 && i<m_width) {
if(y>0 && (*this)[y-1][i]!=0) {
extractConnectedRegion(i, y-1, points);
}
if(y<(m_height-1) && (*this)[y+1][i]!=0) {
extractConnectedRegion(i, y+1, points);
}
}
}
}
inline int findThresholdAtPosition(int startx, int starty, int size, Image* src) {
int total=0;
for(int y=starty; y<starty+size; y++) {
for(int x=startx; x<startx+size; x++) {
total+=(*src)[y][x];
}
}
int threshold=total/(size*size);
return threshold;
};
/*
ImageWrapper* Image::autoLocalThreshold() {
const int local_size=10;
// now produce the thresholded image
Image *result=new Image(m_width, m_height);
// process the image
int threshold=0;
for(int y=local_size/2; y<m_height-local_size/2; y++) {
for(int x=local_size/2; x<m_width-local_size/2; x++) {
threshold=findThresholdAtPosition(x-local_size/2, y-local_size/2, local_size, this);
int val=(*this)[y][x];
if(val>threshold*0.9)
(*result)[y][x]=0;
else
(*result)[y][x]=255;
}
}
return [ImageWrapper imageWithCPPImage:result];
}
*/
ImageWrapper* Image::autoLocalThreshold() {
const int local_size=8;
// now produce the thresholded image
uint8_t *result=(uint8_t*) malloc(m_width*m_height);
// get the initial total
int total=0;
for(int y=0; y<local_size; y++) {
for(int x=0; x<local_size; x++) {
total+=(*this)[y][x];
}
}
// process the image
int lastIndex=m_width*m_height-(m_width*local_size/2+local_size/2);
for(int index=m_width*local_size/2+local_size/2; index<lastIndex; index++) {
int threshold=total/64;
if(m_imageData[index]>threshold*0.9)
result[index]=0;
else
result[index]=255;
// calculate the new total
for(int index2=index-m_width*local_size/2-local_size/2; index2<index+m_width*local_size/2-local_size/2; index2+=m_width) {
total-=m_imageData[index2];
total+=m_imageData[index2+local_size];
}
}
return Image::createImage(result, m_width, m_height, true);
}
ImageWrapper *Image::autoThreshold() {
int total=0;
int count=0;
for(int y=0; y<m_height; y++) {
for(int x=0; x<m_width; x++) {
total+=(*this)[y][x];
count++;
}
}
int threshold=total/count;
Image *result=new Image(m_width, m_height);
for(int y=0; y<m_height; y++) {
for(int x=0; x<m_width; x++) {
if((*this)[y][x]>threshold*0.8) {
(*result)[y][x]=0;
} else {
(*result)[y][x]=255;
}
}
}
return [ImageWrapper imageWithCPPImage:result];
}
#define NOEDGE 255
#define POSSIBLE_EDGE 128
#define EDGE 0
void non_max_supp(int *mag, int *gradx, int *grady, int nrows, int ncols,
uint8_t *result)
{
int rowcount, colcount,count;
int *magrowptr,*magptr;
int *gxrowptr,*gxptr;
int *gyrowptr,*gyptr,z1,z2;
int m00,gx,gy;
float mag1,mag2,xperp,yperp;
uint8_t *resultrowptr, *resultptr;
/****************************************************************************
* Zero the edges of the result image.
****************************************************************************/
for(count=0,resultrowptr=result,resultptr=result+ncols*(nrows-1);
count<ncols; resultptr++,resultrowptr++,count++){
*resultrowptr = *resultptr = (unsigned char) 0;
}
for(count=0,resultptr=result,resultrowptr=result+ncols-1;
count<nrows; count++,resultptr+=ncols,resultrowptr+=ncols){
*resultptr = *resultrowptr = (unsigned char) 0;
}
/****************************************************************************
* Suppress non-maximum points.
****************************************************************************/
for(rowcount=1,magrowptr=mag+ncols+1,gxrowptr=gradx+ncols+1,
gyrowptr=grady+ncols+1,resultrowptr=result+ncols+1;
rowcount<nrows-2;
rowcount++,magrowptr+=ncols,gyrowptr+=ncols,gxrowptr+=ncols,
resultrowptr+=ncols){
for(colcount=1,magptr=magrowptr,gxptr=gxrowptr,gyptr=gyrowptr,
resultptr=resultrowptr;colcount<ncols-2;
colcount++,magptr++,gxptr++,gyptr++,resultptr++){
m00 = *magptr;
if(m00 == 0){
*resultptr = (unsigned char) NOEDGE;
}
else{
xperp = -(gx = *gxptr)/((float)m00);
yperp = (gy = *gyptr)/((float)m00);
}
if(gx >= 0){
if(gy >= 0){
if (gx >= gy)
{
/* 111 */
/* Left point */
z1 = *(magptr - 1);
z2 = *(magptr - ncols - 1);
mag1 = (m00 - z1)*xperp + (z2 - z1)*yperp;
/* Right point */
z1 = *(magptr + 1);
z2 = *(magptr + ncols + 1);
mag2 = (m00 - z1)*xperp + (z2 - z1)*yperp;
}
else
{
/* 110 */
/* Left point */
z1 = *(magptr - ncols);
z2 = *(magptr - ncols - 1);
mag1 = (z1 - z2)*xperp + (z1 - m00)*yperp;
/* Right point */
z1 = *(magptr + ncols);
z2 = *(magptr + ncols + 1);
mag2 = (z1 - z2)*xperp + (z1 - m00)*yperp;
}
}
else
{
if (gx >= -gy)
{
/* 101 */
/* Left point */
z1 = *(magptr - 1);
z2 = *(magptr + ncols - 1);
mag1 = (m00 - z1)*xperp + (z1 - z2)*yperp;
/* Right point */
z1 = *(magptr + 1);
z2 = *(magptr - ncols + 1);
mag2 = (m00 - z1)*xperp + (z1 - z2)*yperp;
}
else
{
/* 100 */
/* Left point */
z1 = *(magptr + ncols);
z2 = *(magptr + ncols - 1);
mag1 = (z1 - z2)*xperp + (m00 - z1)*yperp;
/* Right point */
z1 = *(magptr - ncols);
z2 = *(magptr - ncols + 1);
mag2 = (z1 - z2)*xperp + (m00 - z1)*yperp;
}
}
}
else
{
if ((gy = *gyptr) >= 0)
{
if (-gx >= gy)
{
/* 011 */
/* Left point */
z1 = *(magptr + 1);
z2 = *(magptr - ncols + 1);
mag1 = (z1 - m00)*xperp + (z2 - z1)*yperp;
/* Right point */
z1 = *(magptr - 1);
z2 = *(magptr + ncols - 1);
mag2 = (z1 - m00)*xperp + (z2 - z1)*yperp;
}
else
{
/* 010 */
/* Left point */
z1 = *(magptr - ncols);
z2 = *(magptr - ncols + 1);
mag1 = (z2 - z1)*xperp + (z1 - m00)*yperp;
/* Right point */
z1 = *(magptr + ncols);
z2 = *(magptr + ncols - 1);
mag2 = (z2 - z1)*xperp + (z1 - m00)*yperp;
}
}
else
{
if (-gx > -gy)
{
/* 001 */
/* Left point */
z1 = *(magptr + 1);
z2 = *(magptr + ncols + 1);
mag1 = (z1 - m00)*xperp + (z1 - z2)*yperp;
/* Right point */
z1 = *(magptr - 1);
z2 = *(magptr - ncols - 1);
mag2 = (z1 - m00)*xperp + (z1 - z2)*yperp;
}
else
{
/* 000 */
/* Left point */
z1 = *(magptr + ncols);
z2 = *(magptr + ncols + 1);
mag1 = (z2 - z1)*xperp + (m00 - z1)*yperp;
/* Right point */
z1 = *(magptr - ncols);
z2 = *(magptr - ncols - 1);
mag2 = (z2 - z1)*xperp + (m00 - z1)*yperp;
}
}
}
/* Now determine if the current point is a maximum point */
if ((mag1 > 0.0) || (mag2 > 0.0))
{
*resultptr = (unsigned char) NOEDGE;
}
else
{
if (mag2 == 0.0)
*resultptr = (unsigned char) NOEDGE;
else
*resultptr = (unsigned char) POSSIBLE_EDGE;
}
}
}
}
void follow_edges(uint8_t *edgemapptr, int *edgemagptr, short lowval,
int cols)
{
int *tempmagptr;
uint8_t *tempmapptr;
int i;
int x[8] = {1,1,0,-1,-1,-1,0,1},
y[8] = {0,1,1,1,0,-1,-1,-1};
for(i=0;i<8;i++){
tempmapptr = edgemapptr - y[i]*cols + x[i];
tempmagptr = edgemagptr - y[i]*cols + x[i];
if((*tempmapptr == POSSIBLE_EDGE) && (*tempmagptr > lowval)){
*tempmapptr = (unsigned char) EDGE;
follow_edges(tempmapptr,tempmagptr, lowval, cols);
}
}
}
void apply_hysteresis(int *mag, uint8_t *nms, int rows, int cols,
float tlow, float thigh, uint8_t *edge)
{
int r, c, pos, numedges, highcount, lowthreshold, highthreshold,hist[32768];
int maximum_mag;
/****************************************************************************
* Initialize the edge map to possible edges everywhere the non-maximal
* suppression suggested there could be an edge except for the border. At
* the border we say there can not be an edge because it makes the
* follow_edges algorithm more efficient to not worry about tracking an
* edge off the side of the image.
****************************************************************************/
for(r=0,pos=0;r<rows;r++){
for(c=0;c<cols;c++,pos++){
if(nms[pos] == POSSIBLE_EDGE) edge[pos] = POSSIBLE_EDGE;
else edge[pos] = NOEDGE;
}
}
for(r=0,pos=0;r<rows;r++,pos+=cols){
edge[pos] = NOEDGE;
edge[pos+cols-1] = NOEDGE;
}
pos = (rows-1) * cols;
for(c=0;c<cols;c++,pos++){
edge[c] = NOEDGE;
edge[pos] = NOEDGE;
}
/****************************************************************************
* Compute the histogram of the magnitude image. Then use the histogram to
* compute hysteresis thresholds.
****************************************************************************/
for(r=0;r<32768;r++) hist[r] = 0;
for(r=0,pos=0;r<rows;r++){
for(c=0;c<cols;c++,pos++){
if(edge[pos] == POSSIBLE_EDGE) hist[mag[pos]]++;
}
}
/****************************************************************************
* Compute the number of pixels that passed the nonmaximal suppression.
****************************************************************************/
for(r=1,numedges=0;r<32768;r++){
if(hist[r] != 0) maximum_mag = r;
numedges += hist[r];
}
highcount = (int)(numedges * thigh + 0.5);
/****************************************************************************
* Compute the high threshold value as the (100 * thigh) percentage point
* in the magnitude of the gradient histogram of all the pixels that passes
* non-maximal suppression. Then calculate the low threshold as a fraction
* of the computed high threshold value. John Canny said in his paper
* "A Computational Approach to Edge Detection" that "The ratio of the
* high to low threshold in the implementation is in the range two or three
* to one." That means that in terms of this implementation, we should
* choose tlow ~= 0.5 or 0.33333.
****************************************************************************/
r = 1;
numedges = hist[1];
while((r<(maximum_mag-1)) && (numedges < highcount)){
r++;
numedges += hist[r];
}
highthreshold = r;
lowthreshold = (int)(highthreshold * tlow + 0.5);
/*
if(VERBOSE){
printf("The input low and high fractions of %f and %f computed to\n",
tlow, thigh);
printf("magnitude of the gradient threshold values of: %d %d\n",
lowthreshold, highthreshold);
}
*/
/****************************************************************************
* This loop looks for pixels above the highthreshold to locate edges and
* then calls follow_edges to continue the edge.
****************************************************************************/
for(r=0,pos=0;r<rows;r++){
for(c=0;c<cols;c++,pos++){
if((edge[pos] == POSSIBLE_EDGE) && (mag[pos] >= highthreshold)){
edge[pos] = EDGE;
follow_edges((edge+pos), (mag+pos), lowthreshold, cols);
}
}
}
/****************************************************************************
* Set all the remaining possible edges to non-edges.
****************************************************************************/
for(r=0,pos=0;r<rows;r++){
for(c=0;c<cols;c++,pos++) if(edge[pos] != EDGE) edge[pos] = NOEDGE;
}
}
/*
tlow 0.20-0.50
thigh 0.60-0.90
*/
ImageWrapper *Image::cannyEdgeExtract(float tlow, float thigh) {
int gx[3][3]={
{ -1, 0, 1 },
{ -2, 0, 2 },
{ -1, 0, 1 }};
int gy[3][3]={
{ 1, 2, 1 },
{ 0, 0, 0 },
{ -1, -2, -1 }};
int resultWidth=m_width-3;
int resultHeight=m_height-3;
int *diffx=(int *) malloc(sizeof(int)*resultHeight*resultWidth);
int *diffy=(int *) malloc(sizeof(int)*resultHeight*resultWidth);
int *mag=(int *) malloc(siz
| 归档时间: |
|
| 查看次数: |
4152 次 |
| 最近记录: |