第四周-huang

本文介绍了一个基于OpenCV的Android应用开发案例,主要内容包括如何实现图片的边缘检测处理及用户通过触摸屏幕在图片上做标记的功能。文章详细解释了获取触摸点相对坐标的方法,并演示了如何利用OpenCV进行图片的灰度转换与边缘检测。

日期:2014年10月18日—2014年10月24日


1.本周已完成任务:通过触摸屏幕上显示的图片,在图片上留下标记,类似画图板一样的功能

2.本周未完成任务:简单的区域识别算法设计,整体UI设计

3.下周计划:照相机使用,对焦,保存

4.关键技术点说明:

首先是获得触摸的点在图片中的相对坐标,然后通过控件的OnTouchListener事件获得点击事件,注意这里与onTouch事件不一样的是坐标,onTouch获得的是绝对坐标是相对于屏幕左上角的像素,而OnTouchListener是获得相对于控件左上角的像素,通过控件属性设置将图片显示在左上角从而获取点击的相对坐标。

获得坐标后如果直接在坐标写入一定范围内的颜色,则会出现新的问题——比例不对,由于图片和屏幕不是同等大小,所以图片可能被压缩后显示出来,这个时候可以在图片载入后获取图片的大小和控件的大小来获得缩放比例。

在写入数据的时候需要注意超出图片范围的情况,因为我这里为了方便识别对触摸的点开始右20个像素,下20个像素写入,所以在点击图片右下角的时候会超出范围,这个可以在一开始确定比例的时候就预先减去20来预防。

 

以下程序还是用以前的改的,所以需要先进行边缘处理之后才能正常使用(偷懒啊)。

package com.example.opencv_test;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

	Button btnProcess;
	Bitmap srcBitmap;
	Bitmap grayBitmap;
	ImageView imgHuaishi;
	float scale_bmp;
	private static boolean flag = true;
	private static boolean isFirst = true;
	private static final String TAG = "MainActivity";

	// OpenCV库加载并初始化成功后的回调函数
	private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {

		@Override
		public void onManagerConnected(int status) {
			// TODO Auto-generated method stub
			switch (status) {
			case BaseLoaderCallback.SUCCESS:
				Log.i(TAG, "成功加载");
				break;
			default:
				super.onManagerConnected(status);
				Log.i(TAG, "加载失败");
				break;
			}

		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		btnProcess = (Button) findViewById(R.id.btn_gray_process);
		imgHuaishi = (ImageView) findViewById(R.id.img_huaishi);
		Log.i(TAG, "initUI sucess...");
		imgHuaishi.setOnTouchListener(onTouchListener);
		btnProcess.setOnClickListener(new ProcessClickListener());
	}

	private OnTouchListener onTouchListener = new OnTouchListener() {

		@Override
		public boolean onTouch(View v, MotionEvent event) {
			switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:
				if (!flag) {
				int x,y;
				int j,i;
				x = (int) ((int) event.getX()*scale_bmp);
				y = (int) ((int) event.getY()*scale_bmp);
				Log.i("x,y", String.valueOf(x) + "," + String.valueOf(y));
				for (i = x; i < x + 20; i++)
					for (j = y; j < y + 20; j++)
						grayBitmap.setPixel(i, j, 0xFFFFFF);// 修改像素
				imgHuaishi.setImageBitmap(grayBitmap);
			}
				break;

			default:
				break;
			}

			return false;
		}
	};

	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	public void procSrc2Gray() {
		Mat rgbMat = new Mat();
		Mat grayMat = new Mat();
		srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.r);
		grayBitmap = Bitmap.createBitmap(srcBitmap.getWidth(),
				srcBitmap.getHeight(), Config.RGB_565);
		Utils.bitmapToMat(srcBitmap, rgbMat);// convert original bitmap to Mat,
												// R G B.
		// Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY);//rgbMat to
 		Imgproc.Canny(rgbMat, grayMat, 150, 90);
		Utils.matToBitmap(grayMat, grayBitmap); // convert mat to bitmap
		
		scale_bmp = ((float)grayBitmap.getWidth()-20)/imgHuaishi.getWidth();
		Log.i("bmpscale",String.valueOf(scale_bmp));
		Log.i(TAG, "procSrc2Gray sucess...");
	}

	private class ProcessClickListener implements OnClickListener {

		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			if (isFirst) {
				procSrc2Gray();
				isFirst = false;
			}
			if (flag) {
				imgHuaishi.setImageBitmap(grayBitmap);
				btnProcess.setText("查看原图");
				flag = false;
			} else {
				imgHuaishi.setImageBitmap(srcBitmap);
				btnProcess.setText("边缘处理");
				flag = true;
			}
		}

	}


	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		// load OpenCV engine and init OpenCV library
		OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9,
				getApplicationContext(), mLoaderCallback);
		Log.i(TAG, "onResume sucess load OpenCV...");
	}
}


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.opencv_test.MainActivity"
    tools:ignore="MergeRootFrame" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <Button
            android:id="@+id/btn_gray_process"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="44dp"
            android:text="边缘处理" />

        <ImageView
            android:id="@+id/img_huaishi"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:adjustViewBounds="true"
            android:src="@drawable/r" />

    </RelativeLayout>

</FrameLayout>



<think>嗯,用户想了解如何在Linux crontab中指定每周的某一天执行任务。这个问题很具体,用户应该是在设置定时任务时遇到了具体需求。 用户可能正在配置一个需要每周固定日期运行的脚本或程序,比如每周备份、每周报表生成之类的任务。从问题表述看,用户对crontab有一定基础了解,但不太清楚星期的表示方法。 关于crontab的时间字段,需要特别注意星期字段的特殊性: - 星期字段是第五个字段 - 可以用0-7表示,其中0和7都代表星期日 - 可以用英文缩写如SUN、MON等(部分系统支持) - 这个字段和其他字段是"或"关系,容易产生混淆 用户可能没意识到星期字段如果和日字段同时设置会产生"或"逻辑,这个坑需要重点说明。另外用户可能不知道可以用英文缩写这种更直观的方式。 考虑到用户实际使用场景,应该给出具体示例: - 每周一执行的写法 - 周末执行的两种写法 - 工作日执行的写法 - 避免同时设置日字段的警告 还需要提醒用户注意环境变量问题,很多脚本在crontab中执行失败都是因为缺少环境变量。最后要强调测试的重要性,毕竟时间表达式写错可能导致任务在错误时间执行。 用户的问题虽然简短,但涉及crontab比较核心且容易出错的知识点,需要把原理和陷阱都解释清楚。</think>在 Linux crontab 中,**每周的某一天**是通过时间表达式中的**第五个字段**(星期字段)来指定的。该字段使用数字 `0` 到 `7` 表示星期日到星期六(其中 `0` 和 `7` 都代表星期日),也可以使用英文缩写(部分系统支持)。 ### 星期字段详解 1. **位置:** 时间表达式的第五个字段(共五个字段:分钟、小时、日、月、星期)。 2. **取值范围:** * `0` 或 `7`:星期日 (Sunday) * `1`:星期一 (Monday) * `2`:星期二 (Tuesday) * `3`:星期三 (Wednesday) * `4`:星期四 (Thursday) * `5`:星期五 (Friday) * `6`:星期六 (Saturday) 3. **英文缩写(部分系统支持):** 可以使用 `SUN`, `MON`, `TUE`, `WED`, `THU`, `FRI`, `SAT`。使用缩写时**通常不区分大小写**(例如 `mon` 或 `MON` 通常都可以)。 4. **重要规则:** * **“或”逻辑:** 星期字段和日字段(第三个字段)是**“或”**关系,而非“与”关系。这意味着如果**日字段**或**星期字段**中有一个被满足,任务就会执行。 * **避免冲突:** 如果希望任务只在特定的日期(比如每月的15号)**并且**是特定的星期几(比如星期三)执行,需要同时设置日字段和星期字段。但如果日字段设为 `*`(每天),那么只要星期字段匹配,任务就会执行,无论日字段是什么值。 ### 常用示例 假设你想让任务在每周一早上9点30分执行: * **使用数字:** ```bash 30 9 * * 1 /path/to/your/command ``` 解释:30分钟, 9点, 任意日, 任意月, 星期一 (1) * **使用英文缩写(如果系统支持):** ```bash 30 9 * * MON /path/to/your/command ``` ### 其他常见需求示例 1. **每周日午夜(00:00)执行:** ```bash 0 0 * * 0 /path/to/command # 使用 0 # 或 0 0 * * 7 /path/to/command # 使用 7 # 或 (如果支持) 0 0 * * SUN /path/to/command ``` 2. **每周六和周日早上8点执行:** ```bash 0 8 * * 6,0 /path/to/command # 使用数字 6 (Sat) 和 0 (Sun) # 或 0 8 * * 6,7 /path/to/command # 使用数字 6 (Sat) 和 7 (Sun) # 或 (如果支持) 0 8 * * SAT,SUN /path/to/command ``` 3. **每周一到周五下午5点执行(工作日):** ```bash 0 17 * * 1-5 /path/to/command # 使用数字范围 1 (Mon) 到 5 (Fri) # 或 (如果支持) 0 17 * * MON-FRI /path/to/command ``` 4. **每月1号,并且这天是星期三时,中午12点执行:** ```bash 0 12 1 * 3 /path/to/command # 日字段=1, 星期字段=3 (Wed) ``` *注意:* 这个任务会在每月1号执行,**并且**在1号是星期三时也执行(因为“或”逻辑)。如果1号不是星期三,它仍然会在1号执行一次(因为日字段=1),在星期三也会执行一次(如果星期三不是1号)。要**严格**只在“1号且是星期三”执行,需要额外逻辑(例如在命令脚本中检查当天是否是1号)。 ### 关键提示 1. **测试表达式:** 使用在线工具(如 [crontab.guru](https://crontab.guru/) 或 [crontab-generator.org](https://crontab-generator.org/))验证你的cron表达式是否符合预期。 2. **环境变量:** 在crontab中执行的命令可能没有你在终端中拥有的完整环境变量。如果脚本依赖于环境变量(如 `PATH`, `JAVA_HOME` 等),需要在crontab文件顶部定义它们,或者在命令脚本中显式设置,或者在命令前加载环境配置文件(如 `. /etc/profile;` 或 `. /home/user/.bash_profile;`)[^4]。例如: ```bash SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin MAILTO=your_email@example.com # 接收任务输出邮件 0 9 * * 1 /path/to/your/command ``` 3. **命令路径:** 尽量在命令中使用**绝对路径**,避免因cron的 `PATH` 环境变量不同而导致找不到命令。 4. **输出处理:** 默认情况下,cron会将命令的标准输出和错误通过邮件发送给任务所有者(通常是用户)。如果不需要邮件,可以将输出重定向: ```bash 0 9 * * 1 /path/to/command > /dev/null 2>&1 # 丢弃所有输出 0 9 * * 1 /path/to/command >> /path/to/logfile.log 2>&1 # 追加输出到日志文件 ``` 5. **编辑crontab:** 使用 `crontab -e` 命令编辑当前用户的crontab文件。使用 `crontab -l` 查看当前用户的crontab内容。系统级的crontab通常编辑 `/etc/crontab` 文件(需要root权限)[^1][^3]。 通过正确设置第五个字段(星期字段),你就可以精确地控制任务在每周的特定一天或多天自动执行[^1][^2][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值