Android相机实时⾃动对焦的完美实现(带源码)Android相机实时⾃动对焦的完美实现
想写这篇⽂章很久了,去年⼗⽉份接触了相机这⼀块的知识,由于android碎⽚化严重,⽽且各⼤⼚商极有可能去修改相关API的实现,其中遇到了不少坑,包括实时相机⾼斯模糊,⾃动对焦的兼容问题,以及⼀系列性能问题。换过很多搜索引擎,访问过很多⽹站,访问过很多⽹站,拜读过很多代码,没有发现对于相机实时⾃动对焦特别完美的实现⽅式。现对相机的⾃动对焦问题单独做⼀个记录,算是对这部分的⼀个总结。也希望后⼈在这部分能够快速地解决问题,不必浪费过多的时间。测试⼿机包括:MX4 pro,⼩⽶4,华为荣耀3C等等。
参考过@yanzi1225627 ⼤神的⼀些做法,测试结果不是特别满意。
⼀,⼀些对焦⽅案的尝试
1,autoFocus()的尝试:
<code class="language-java hljs  has-numbering" >
<span class="hljs-keyword" >private</span> Camera.AutoFocusCallback
mAutoFocusCallback;
mAutoFocusCallback = <span class="hljs-keyword" >new</span>
Camera.AutoFocusCallback() {
<span class="hljs-keyword" >public</span> <span class="hljs-keyword" >void</span> <span class="hljs-title" >onAutoFocus</span>(<span
class="hljs-keyword" >boolean</span> success, Camera camera) {
<span class="hljs-comment" >// TODO Auto-generated method stub</span>
<span class="hljs-keyword" >if</span>(success){
myCamera.setOneShotPreviewCallback(<span class="hljs-keyword" >null</span>);
Toast.makeText(TestPhotoActivity.<span class="hljs-keyword" >this</span>,
<span class="hljs-string" >"⾃动聚焦成功"</span> , Toast.LENGTH_SHORT).show();
}
}
};
myCamera.autoFocus(mAutoFocusCallback);
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top:
0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li> <li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li></ul>
在⼀部分⼿机上,始终只对焦⼀次,也就是说根本不能实现。即使是在按下拍照的时候去调⽤⼀次对焦,等对焦成功后再进⾏拍照,实现的效果也不是很完美。还见部分博客把autoFocus()⽅法放在Camera预览SurfaceView的surfaceChanged()中的⼀些实现,发现也只对焦了⼀次。
2,设置对焦模式FOCUS_MODE_CONTINUOUS_PICTURE
radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">        /**
* Continuous auto focus mode intended <span class="hljs-keyword" >for</span> taking pictures. The camera
* continuously tries <span class="hljs-keyword" >to</span> focus. The speed <span class="hljs-keyword" >of</span> focus change <span class="hljs-keyword" >is</span> more
* aggressive than {@link <span class="hljs-comment" >#FOCUS_MODE_CONTINUOUS_VIDEO}. Auto focus</span>
* starts when <span class="hljs-keyword" >the</span> parameter <span class="hljs-keyword" >is</span> <span class="hljs-keyword" >set</span>.
*
* <p>Applications can call {@link <span class="hljs-comment" >#autoFocus(AutoFocusCallback)} in</span>
* this mode. If <span class="hljs-keyword" >the</span> autofocus <span class="hljs-keyword" >is</span> <span class="hljs-keyword" >in</span> <span class="hljs-keyword" >the</span> <span class="hljs-keyword" >middle</span> <span class="hljs-keyword" >of</span> scanning, <span class="hljs-keyword" >the</span> focus
* callback will <span class="hljs-constant" >return</span> when <span class="hljs-keyword" >it</span> completes. If <span class="hljs-keyword" >the</s
pan> autofocus <span class="hljs-keyword" >is</span> <span class="hljs-keyword" >not</span>
* scanning, <span class="hljs-keyword" >the</span> focus callback will immediately <span class="hljs-constant" >return</span> <span class="hljs-keyword" >with</span> a <span class="hljs-type" >boolean</span>
* <span class="hljs-keyword" >that</span> indicates whether <span class="hljs-keyword" >the</span> focus <span class="hljs-keyword" >is</span> sharp <span class="hljs-keyword" >or</span> <span
class="hljs-keyword" >not</span>. The apps can <span class="hljs-keyword" >then</span>
* decide <span class="hljs-keyword" >if</span> t
hey want <span class="hljs-keyword" >to</span> take a picture immediately <span class="hljs-keyword" >or</span> <span class="hljs-keyword" >to</span> change <span class="hljs-keyword" >the</span>
* focus mode <span class="hljs-keyword" >to</span> auto, <span class="hljs-keyword" >and</span> <span class="hljs-command" >run</span> a full autofocus cycle. The focus
* position <span class="hljs-keyword" >is</span> locked <span class="hljs-keyword" >after</span> autoFocus call. If applications want <span class="hljs-keyword" >to</span>
* resume <span class="hljs-keyword" >the</span> continuous focus, cancelAutoFocus must be called.
* Restarting <span class="hljs-keyword" >the</span> preview will <span class="hljs-keyword" >not</span> resume <span class="hljs-keyword" >the</span> continuous autofocus. To
* stop continuous focus, applications should change <span class="hljs-keyword" >the</span> focus mode <span class="hljs-keyword" >to</span>
* other modes.
*
* @see <span class="hljs-comment" >#FOCUS_MODE_CONTINUOUS_VIDEO</span>
*/
public static final String FOCUS_MODE_CONTINUOUS_PICTURE = <span class="hljs-string" >"continuous-picture"</span>;
</code><ul class="pre-numbering" ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li> <li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li><li >16</li><li >17</li><li >18</li><li >19</li><li >2
0</li><li >21</li><li >22</li><li >23</li></ul>
0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">    setFocusMode(Camera<span class="hljs-preprocessor"
>.Parameters</span><span class="hljs-preprocessor" >.FOCUS</span>_MODE_CONTINUOUS_PICTURE)<span class="hljs-comment" >;</span></code><ul class="pre-numbering" ><li >1</li></ul>
在⼤部分⼿机上实现了⾃动对焦,⽽且效果还不错,⽽且不需要去额外调⽤⽅法。但是测试后发现⼩⽶4机型不会⾃动对焦。
3,设置对焦模式为FOCUS_MODE_CONTINUOUS_VIDEO
radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">        /**
* Continuous auto focus mode intended <span class="hljs-keyword" >for</span> video recording. The camera
* continuously tries <span class="hljs-keyword" >to</span> focus. This <span
class="hljs-keyword" >is</span> <span class="hljs-keyword" >the</span> best choice <span class="hljs-keyword" >for</span> video
* recording because <span class="hljs-keyword" >the</span> focus changes smoothly . Applications still can
* call {@link <span class="hljs-comment" >#takePicture(Camera.ShutterCallback,
</span>
* Camera.PictureCallback, Camera.PictureCallback)} <span class="hljs-keyword" >in</span> this mode <span class="hljs-keyword" >but</span> <span class="hljs-keyword" >the</span>
* subject may <span class="hljs-keyword" >not</span> be <span class="hljs-keyword" >in</span> focus. Auto focus starts when <span class="hljs-keyword" >the</span> parameter <span class="hljs-keyword" >is</span>
* <span class="hljs-keyword" >set</span>.
*
* <p>Since API level <span class="hljs-number" >14</span>, applications can call {@link
* <span class="hljs-comment" >#autoFocus(AutoFocusCallback)} in this mode. The focus callback will</span>
* immediately <span class="hljs-constant" >return</span> <span class="hljs-keyword" >with</span> a <span class="hljs-type" >boolean</span> <span class="hljs-keyword" >that</span> indicates whether <span class="hljs-keyword" >the</span> focus <span class="hljs-keyword" >is</span>
* sharp <span class="hljs-keyword" >or</span> <span class="hljs-keyword"
>not</span>. The focus position <span class="hljs-keyword" >is</span> locked <span class="hljs-keyword" >after</span> autoFocus call. If
* applications want <span class="hljs-keyword" >
to</span> resume <span class="hljs-keyword" >the</span> continuous focus, cancelAutoFocus
* must be called. Restarting <span class="hljs-keyword" >the</span> preview will
<span class="hljs-keyword" >not</span> resume <span class="hljs-keyword" >the</span> continuous
* autofocus. To stop continuous focus, applications should change <span class="hljs-keyword" >the</span>
* focus mode <span class="hljs-keyword" >to</span> other modes.
*
* @see <span class="hljs-comment" >#FOCUS_MODE_CONTINUOUS_PICTURE</span>
*/
public static final String FOCUS_MODE_CONTINUOUS_VIDEO = <span class="hljs-string" >"continuous-video"</span>;</code><ul class="pre-numbering" ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li><li >10</li><li >11</li><li >12</li><li >13</li><li
>14</li><li >15</li><li >16</li><li >17</li><li >18</li><li >19</li><li >20</li><li >21</li></ul>
<code class="hljs avrasm has-numbering" >    setFocusMode(Camera<span class="hljs-preprocessor" >.Parameters</span><span class="hljs-preprocessor" >.FOCUS</span>_MODE_CONTINUOUS_VIDEO)<span class="hljs-comment" >;</span></code><ul class="pre-numbering" ><li style="box-sizi
ng: border-box; padding: 0px 5px;">1</li></ul>
经过测试,发现⼤部分⼿机可以连续对焦,但是在对焦过程中屏幕会连续闪烁,⽽且体验极其不好。魅族MX4不⽀持此种⽅式的对焦。也就是说第⼆,第三种⽅案都要放弃。
4,触摸对焦
本来在⼀番焦头烂额后准备妥协,先把触摸对焦实现吧。基本思路是⽀持定点对焦,就调⽤定点对焦,否则调⽤autoFocus()。
<code class="hljs java has-numbering" >  <span class="hljs-javadoc" >/**
* ⼿动聚焦box sizing
*
*<span class="hljs-javadoctag" > @param</span> point 触屏坐标
*/</span>
<span class="hljs-keyword" >protected</span> <span class="hljs-keyword" >boolean</span> <span class="hljs-title" >onFocus</span>(Point point, Camera.AutoFocusCallback callback) {
<span class="hljs-keyword" >if</span> (mCamera == <span class="hljs-keyword"
>null</span>) {
<span class="hljs-keyword" >return</span> <span class="hljs-keyword" >false</span>;
}
Camera.Parameters parameters = <span class="hljs-keyword" >null</span>;
<span class="hljs-keyword" >try</span> {
parameters = Parameters();
} <span class="hljs-keyword" >catch</span> (Exception e) {
e.printStackTrace();
<span class="hljs-keyword" >return</span> <span class="hljs-keyword" >false</span>;
}
<span class="hljs-comment" >//不⽀持设置⾃定义聚焦,则使⽤⾃动聚焦,返回</span>        <span class="hljs-keyword" >if</span>(Build.VERSION.SDK_INT >= <span class="hljs-number" >14</span>) {
<span class="hljs-keyword" >if</span> (MaxNumFocusAreas() <= <span class="hljs-number" >0</span>) {
<span class="hljs-keyword" >return</span> focus(callback);
}
Log.i(TAG, <span class="hljs-string" >"onCameraFocus:"</span> + point.x + <span class="hljs-string" >","</span> + point.y);
<span class="hljs-comment" >//定点对焦</span>
List<Camera.Area> areas = <span class="hljs-keyword" >new</span>
ArrayList<Camera.Area>();
<span class="hljs-keyword" >int</span> left = point.x - <span class="hljs-number"
>300</span>;
<span class="hljs-keyword" >int</span> top = point.y - <span class="hljs-number"
>300</span>;
<span class="hljs-keyword" >int</span> right = point.x + <span class="hljs-number"
>300</span>;
<span class="hljs-keyword" >int</span> bottom = point.y + <span class="hljs-
number" >300</span>;
left = left < -<span class="hljs-number" >1000</span> ? -<span class="hljs-
number" >1000</span> : left;
top = top < -<span class="hljs-number" >1000</span> ? -<span class="hljs-
number" >1000</span> : top;
right = right > <span class="hljs-number" >1000</span> ? <span class="hljs-number" >1000</span> : right;
bottom = bottom > <span class="hljs-number" >1000</span> ? <span class="hljs-number" >1000</span> : bottom;
areas.add(<span class="hljs-keyword" >new</span> Camera.Area(<span
class="hljs-keyword" >new</span> Rect(left, top, right, bottom), <span class="hljs-number"
>100</span>));
parameters.setFocusAreas(areas);
<span class="hljs-keyword" >try</span> {

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。