C#实现bitmap图像矫正
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Diagnostics;
using System.Drawing.Imaging; //窗体调用 private Bitmap RotateImage(Bitmap bmp, double angle)
{
Graphics g = null;
Bitmap tmp = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format32bppRgb);
tmp.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
g = Graphics.FromImage(tmp);
try
{
g.FillRectangle(Brushes.White, , , bmp.Width, bmp.Height);
g.RotateTransform((float)angle);
g.DrawImage(bmp, , );
}
finally
{
g.Dispose();
}
return tmp;
} private void button1_Click(object sender, EventArgs e)
{ string fnIn = "f:\\test\\image0097_4.tif";
string fnOut = "f:\\test\\output.tif";
Bitmap bmpIn = new Bitmap(fnIn);
gmseDeskew sk = new gmseDeskew(bmpIn);
double skewangle = sk.GetSkewAngle();
Bitmap bmpOut = RotateImage(bmpIn, -skewangle);
bmpOut.Save(fnOut, ImageFormat.Tiff);//此处简单保存,可采用压缩方式保存
} #region 算法处理类 public class gmseDeskew
{
public class HougLine
{
// Count of points in the line.
public int Count;
// Index in Matrix.
public int Index;
// The line is represented as all x,y that solve y*cos(alpha)-x*sin(alpha)=d
public double Alpha;
public double d;
}
Bitmap cBmp;
double cAlphaStart = -;
double cAlphaStep = 0.2;
int cSteps = * ;
double[] cSinA;
double[] cCosA;
double cDMin;
double cDStep = ;
int cDCount;
// Count of points that fit in a line.
int[] cHMatrix;
public double GetSkewAngle()
{
gmseDeskew.HougLine[] hl = null;
int i = ;
double sum = ;
int count = ;
// Hough Transformation Calc();
// Top 20 of the detected lines in the image.
hl = GetTop();
// Average angle of the lines
for (i = ; i <= ; i++)
{
sum += hl[i].Alpha;
count += ;
}
return sum / count;
}
private HougLine[] GetTop(int Count)
{
HougLine[] hl = null;
int i = ;
int j = ;
HougLine tmp = null;
int AlphaIndex = ;
int dIndex = ;
hl = new HougLine[Count + ];
for (i = ; i <= Count - ; i++)
{
hl[i] = new HougLine();
}
for (i = ; i <= cHMatrix.Length - ; i++)
{
if (cHMatrix[i] > hl[Count - ].Count)
{
hl[Count - ].Count = cHMatrix[i];
hl[Count - ].Index = i;
j = Count - ;
while (j > && hl[j].Count > hl[j - ].Count)
{
tmp = hl[j];
hl[j] = hl[j - ];
hl[j - ] = tmp; j -= ;
}
}
}
for (i = ; i <= Count - ; i++)
{
dIndex = hl[i].Index / cSteps;
AlphaIndex = hl[i].Index - dIndex * cSteps;
hl[i].Alpha = GetAlpha(AlphaIndex);
hl[i].d = dIndex + cDMin;
}
return hl;
}
public gmseDeskew(Bitmap bmp)
{
cBmp = bmp;
}
private void Calc()
{
int x = ;
int y = ;
int hMin = cBmp.Height / ;
int hMax = cBmp.Height * / ;
Init();
for (y = hMin; y <= hMax; y++)
{
for (x = ; x <= cBmp.Width - ; x++)
{ // Only lower edges are considered.
if (IsBlack(x, y))
{
if (!IsBlack(x, y + ))
{
Calc(x, y);
}
}
}
}
}
private void Calc(int x, int y)
{
int alpha = ;
double d = ;
int dIndex = ;
int Index = ;
for (alpha = ; alpha <= cSteps - ; alpha++)
{
d = y * cCosA[alpha] - x * cSinA[alpha];
dIndex = (int)CalcDIndex(d);
Index = dIndex * cSteps + alpha;
try
{
cHMatrix[Index] += ;
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
}
private double CalcDIndex(double d)
{
return Convert.ToInt32(d - cDMin);
}
private bool IsBlack(int x, int y)
{
Color c = default(Color);
double luminance = ;
c = cBmp.GetPixel(x, y);
luminance = (c.R * 0.299) + (c.G * 0.587) + (c.B * 0.114);
return luminance < ;
}
private void Init()
{
int i = ;
double angle = ;
// Precalculation of sin and cos.
cSinA = new double[cSteps];
cCosA = new double[cSteps];
for (i = ; i <= cSteps - ; i++)
{
angle = GetAlpha(i) * Math.PI / 180.0;
cSinA[i] = Math.Sin(angle);
cCosA[i] = Math.Cos(angle);
} // Range of d:
cDMin = -cBmp.Width;
cDCount = (int)( * (cBmp.Width + cBmp.Height) / cDStep);
cHMatrix = new int[cDCount * cSteps + ];
}
public double GetAlpha(int Index)
{
return cAlphaStart + Index * cAlphaStep;
}
} #endregion
具体算法为:由左边界开始扫描,从开始发现黑色素到黑色素达到平均值,在这个距离内的长度和版心的高度通过直角三角形的函数进行换算,这样就知道了倾斜的角度。
C#实现bitmap图像矫正的更多相关文章
- [翻译]开发文档:android Bitmap的高效使用
内容概述 本文内容来自开发文档"Traning > Displaying Bitmaps Efficiently",包括大尺寸Bitmap的高效加载,图片的异步加载和数据缓存 ...
- 【开源毕设】一款精美的家校互动APP分享——爱吖校推 [你关注的,我们才推](持续开源更新3)附高效动态压缩Bitmap
一.写在前面 爱吖校推如同它的名字一样,是一款校园类信息推送交流平台,这么多的家校互动类软件,你选择了我,这是我的幸运.从第一次在博客园上写博客到现在,我一次一次地提高博文的质量和代码的可读性,都是为 ...
- Android Bitmap 和 ByteArray的互相转换
Android Bitmap 和 ByteArray的互相转换 移动平台图像处理,需要将图像传给native处理,如何传递?将bitmap转换成一个 byte[] 方便传递也方便cpp代码直接处理图像 ...
- Android-Drawable、Bitmap、byte[]、资源文件相互转换
我们在Android的开发中,经常可以遇到图片的处理,当中,有很多是 Bitmap.Drawable.byte[]和资源文件它们直接相互转换. 今天就此总结一下: 1.资源文件转为Drawable 2 ...
- bitmap对海量无重复的整数排序--转
原文地址:http://blog.csdn.net/u013074465/article/details/46956295 现在有n个无重复的正整数(n 小于10的7次方),如果内存限制在1.5M以内 ...
- 基于位图(Bitmap、BitmapData)的图片处理方法(C#)
目前操作位图的主流方法有三种: 1.基于Bitmap像素的处理方法,以GetPixel()和SetPixel()方法为主.方法调用简单,但是效率偏低. 2.基于内存的像素操作方法,以System.Ru ...
- android:布局、绘制、内存泄露、响应速度、listview和bitmap、线程优化以及一些优化的建议!
1.布局优化 首先删除布局中无用的控件和层级,其次有选择地使用性能较低的viewgroup,比如布局中既可以使用RelativeLayout和LinearLayout,那我们就采用LinearLayo ...
- 获取View的截图-将View转换为Bitmap对象
开发中,有时候需要获取View的截图来做动画来达到动画流程的目的 原理:将View的内容画到一个Bitmap画布上,然后取出 下面封装了一个从View生成Bitmap的工具类 /** * 将View转 ...
- bitmap解码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define BYTE unsigned c ...
随机推荐
- 【u240】棋子放置
Time Limit: 1 second Memory Limit: 128 MB 小虎刚刚上了幼儿园,老师让他做一个家庭作业:首先画3行格子,第一行有三个格子,第二行有2个格子,第三行有1个格子. ...
- [Clojure] A Room-Escape game, playing with telnet and pure-text commands - Part 3
Code Path: https://github.com/bluesilence/Lisp/blob/master/clojure/projects/room-escape/src/room_esc ...
- tombstone问题分析
tombstone文件包含了发生问题的进程ID信息 I/DEBUG ( 241): pid: 244, tid: 244, name: mediaserver >>> /system ...
- Docker + .NET Core(三)-两种发布方式
原文:Docker + .NET Core(三)-两种发布方式 第一种,自己手写dockerfile发布,上传至hubDocker 正常发布到文件夹中,发布文件上传至linux机器上.如 /www/a ...
- 【30.00%】【vijos 1909】寻找道路
描述 在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到 终点的路径,该路径满足以下条件: 路径上的所有点的出边所指向的点都直接或间接与终点连通. 在满足条件 1 的情 ...
- 【63.63%】【codeforces 724A】Checking the Calendar
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- C-order/Fortran-order(Row-/Column-major order)
1. row-major / column-major order 无论是行序优先还是列序优先,其实在计算机计算中,指的都是在线性空间(linear storage,如 RAM,也即连续内存存储 co ...
- JieBaNet+Lucene.Net
基于JieBaNet+Lucene.Net实现全文搜索 实现效果: 上一篇文章有附全文搜索结果的设计图,下面截一张开发完成上线后的实图: 基本风格是模仿的百度搜索结果,绿色的分页略显小清新. 目前 ...
- Docker container 集装箱说明
容器操作 使用 docker 命令行操作 docker 容器 启动容器 core@localhost ~ $ docker run Usage: docker run [OPTIONS] IMAGE ...
- HistCite 引文分析软件的利器
所需工具及网站清单, HISTCITE:DOWNLOAD YOUR FREE COPY. 提交自己的基本信息即可,十分简单: SCI数据库官网(web of science):http://apps. ...