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 ...
随机推荐
- 通过手机其他iOS应用打开此文件
根据所处理文档的格式,提供本地设备(InApp)能处理该格式文档的所有应用(App).比如,demo中所处理的是pdf格式的文档,那么可以打开该文档的本地app有邮件.打印等等.仅支持ARC. dem ...
- UITableView的一些事1
方法1: _tableview = [[UITableView alloc]initWithFrame:CGRectMake(0, 0,self.view.bounds.size.width,self ...
- 【BZOJ 1033】 [ZJOI2008]杀蚂蚁antbuster(判断线段是否和圆相交)
[题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1033 [题意] https://www.zybuluo.com/Jerusalem/n ...
- Android Studio如何删除module
当你想在Android Studio中删除某个module时,大家习惯性的做法都是选中要删除的module,右键去找delete.但是 在Android Studio中你选中module,右键会发现没 ...
- JPEG图像扩展信息读取和修改
最近,项目需要使用jpg图像信息被写入(非水印),经过研究发现,Android已封装的读者jpg图片扩展信息api(ExifInterface). 通讯api住址:http://developer.a ...
- Qt保存界面配置到注册表
//需要使用QSetting #include<QSettings> 声明函数 protected: void closeEvent(QCloseEvent *event); privat ...
- Windows DPI Awareness for WPF
原文 Windows DPI Awareness for WPF 对于 WPF 程序,要控制程序的 DPI 感知程度,可在 App.manifest 中添加如下代码. 本文知识已经陈旧,你可以阅读这两 ...
- PHP关联数组教程
PHP 数组 关联数组 什么是数组?在使用 PHP 进行开发的过程中,或早或晚,您会需要创建许多相似的变量.无需很多相似的变量,你可以把数据作为元素存储在数组中.数组中的元素都有自己的 ID,因此可以 ...
- 4 DDD里面的界限上下文
1 界限上下文概念的出现 当开发一个电子商务系统的时候,会给系统划分很多子域,销售子域是核心子域,此外还有物流子域,商品子域等支撑子域.在这些子域里面,一个商品product在销售子域和商品子域里面外 ...
- Microsoft IoT Starter Kit
Microsoft IoT Starter Kit 开发初体验 1. 引子 今年6月底,在上海举办的中国国际物联网大会上,微软中国面向中国物联网社区推出了Microsoft IoT Starter K ...