draw_hollow.h

  name="google_ads_frame" marginwidth="0" marginheight="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-5572165936844014&dt=1194442938015&lmt=1194190197&format=336x280_as&output=html&correlator=1194442937843&url=file%3A%2F%2F%2FC%3A%2FDocuments%2520and%2520Settings%2Flhh1%2F%E6%A1%8C%E9%9D%A2%2FCLanguage.htm&color_bg=FFFFFF&color_text=000000&color_link=000000&color_url=FFFFFF&color_border=FFFFFF&ad_type=text&ga_vid=583001034.1194442938&ga_sid=1194442938&ga_hid=1942779085&flash=9&u_h=768&u_w=1024&u_ah=740&u_aw=1024&u_cd=32&u_tz=480&u_java=true" frameborder="0" width="336" scrolling="no" height="280" allowtransparency="allowtransparency"> #define IDM_EXIT           100
#define IDM_TEST           200
#define IDM_ABOUT          301

LRESULT CALLBACK WndProc  (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About    (HWND, UINT, WPARAM, LPARAM);

import cv2 import imageio import numpy as np from PIL import Image, ImageDraw, ImageFont import os import pandas as pd import tqdm def read_gif(gif_path): try: # 使用 imageio 读取 GIF 文件 gif = imageio.get_reader(gif_path) # 只需要获取第一帧就行了 frame = gif.get_data(0) # 将 imageio 读取的帧转换为 OpenCV 可以处理的 BGR 格式 frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) # 直接裁剪指定区域 x, y, w, h = 438, 61, 282, 282 cropped = frame[y:y + h, x:x + w] # cv2.imshow("info",cropped) # cv2.waitKey(0) # 处理裁剪后的图像 cropped_gray = cv2.cvtColor(cropped, cv2.COLOR_BGR2GRAY) _, cropped_thresh = cv2.threshold(cropped_gray, 127, 255, cv2.THRESH_BINARY) # 使用 RETR_TREE 模式查找轮廓,获取层级信息 cropped_contours, cropped_hierarchy = cv2.findContours(cropped_thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) result_text = "未检测到图形,\n视为错误。" text_color = (0, 0, 255) # 默认红色 has_hollow_contour = False # 标记是否检测到空心轮廓 if len(cropped_contours) > 0: for i, contour in enumerate(cropped_contours): # 检查是否存在子轮廓(即是否为空心) if cropped_hierarchy[0][i][2] != -1: has_hollow_contour = True result_text = "检测到空心轮廓,\n视为正确。" text_color = (0, 255, 0) # 绿色 # 绘制外部轮廓 cv2.drawContours(cropped, [contour], -1, text_color, 2) # 绘制内部空心轮廓 child_index = cropped_hierarchy[0][i][2] while child_index != -1: cv2.drawContours(cropped, [cropped_contours[child_index]], -1, text_color, 2) # 绿色绘制内部轮廓 child_index = cropped_hierarchy[0][child_index][0] # 如果没有检测到空心轮廓,则视为检测到实心轮廓 if not has_hollow_contour: result_text = "检测到实心或不封闭轮廓,\n视为错误。" text_color = (0, 0, 255) # 红色 largest_contour = max(cropped_contours, key=cv2.contourArea) cv2.drawContours(cropped, [largest_contour], -1, text_color, 2) # 使用 PIL 显示中文 cropped_pil = Image.fromarray(cv2.cvtColor(cropped, cv2.COLOR_BGR2RGB)) draw = ImageDraw.Draw(cropped_pil) # 需要根据实际情况替换字体文件路径 font = ImageFont.truetype("simhei.ttf", 20) text_color_rgb = tuple(reversed(text_color)) # 转换 BGR 到 RGB draw.text((10, 30), result_text, font=font, fill=text_color_rgb) cropped = cv2.cvtColor(np.array(cropped_pil), cv2.COLOR_RGB2BGR) # 显示裁剪后的图片 cv2.imshow('Cropped Largest Rectangle', cropped) cv2.waitKey(100) # 若结果包含错误信息,视为检测到错误 if "错误" in result_text: return True else: return False except Exception as e: print(f"处理 {gif_path} 时出错: {e}") return True def main(): # 定义四个大文件夹路径 parent_folders = ["A12_1", "A12_2", "A13_1", "A13_2"] error_data = [] gif_files = [] # 收集所有 GIF 文件路径 for parent_folder in parent_folders: for root, dirs, files in os.walk(parent_folder): for file in files: if file.lower().endswith('.gif'): gif_files.append(os.path.join(root, file)) # 使用 tqdm 显示进度条 for gif_path in tqdm.tqdm(gif_files, desc="处理 GIF 文件", unit="个"): is_error = read_gif(gif_path) if is_error: error_data.append({ "编号": os.path.basename(os.path.dirname(gif_path)), "所属大文件夹": next((folder for folder in parent_folders if folder in gif_path), "未知"), "错误图像文件路径": gif_path }) # 关闭opencv窗口 cv2.destroyAllWindows() # 将错误数据保存到 Excel if error_data: df = pd.DataFrame(error_data) df.to_excel("error_images.xlsx", index=False) print("错误图片信息已保存到 error_images.xlsx") else: print("未检测到错误图片") if __name__ == "__main__": main() ————这是一个识别图像的代码,我是一名初学者,请详细为我解释,并且告诉我怎么使用这个代码
06-25
#include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "driverlib/ssi.h" #include "driverlib/pin_map.h" // OLED屏幕尺寸定义 #define OLED_WIDTH 128 #define OLED_HEIGHT 64 #define OLED_PAGES (OLED_HEIGHT/8) // 蛇游戏参数 #define SNAKE_MAX_LENGTH 100 #define INITIAL_SPEED 150 #define FOOD_SIZE 2 // 方向控制 typedef enum { UP, DOWN, LEFT, RIGHT } Direction; // 游戏状态 typedef struct { uint8_t snakeX[SNAKE_MAX_LENGTH]; uint8_t snakeY[SNAKE_MAX_LENGTH]; uint8_t length; Direction direction; uint8_t foodX; uint8_t foodY; uint32_t speed; bool gameOver; } GameState; // OLED命令/数据定义 #define OLED_CMD 0 #define OLED_DAT 1 // 系统时钟频率 uint32_t g_ui32SysClock; // 游戏状态 GameState game; // OLED初始化命令序列 const uint8_t oledInitCmds[] = { 0xAE, // 关闭显示 0xD5, 0x80, // 设置显示时钟分频 0xA8, 0x3F, // 设置复用率 0xD3, 0x00, // 设置显示偏移 0x40, // 设置起始行 0x8D, 0x14, // 电荷泵设置 0x20, 0x00, // 内存地址模式 0xA1, // 段重映射 0xC8, // COM扫描方向 0xDA, 0x12, // COM硬件引脚配置 0x81, 0xCF, // 对比度设置 0xD9, 0xF1, // 预充电周期 0xDB, 0x40, // VCOMH设置 0xA4, // 显示全部打开 0xA6, // 正常显示 0xAF // 开启显示 }; // 函数原型声明 void OLED_Write(uint8_t data, uint8_t mode); void OLED_Init(void); void OLED_Clear(void); void OLED_DrawPixel(uint8_t x, uint8_t y, bool color); void OLED_DrawRect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, bool color); void InitGame(void); void GenerateFood(void); void UpdateSnake(void); void RenderGame(void); void ProcessInput(void); void DelayMs(uint32_t ui32Ms); void DrawGameOver(void); // OLED写函数 void OLED_Write(uint8_t data, uint8_t mode) { uint32_t dummy; // 设置DC引脚(命令/数据) GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, mode ? GPIO_PIN_0 : 0); // 等待SSI发送完成 while(SSIBusy(SSI0_BASE)); // 发送数据 SSIDataPut(SSI0_BASE, data); // 等待发送完成 while(SSIBusy(SSI0_BASE)); // 读取当前数据 SSIDataGet(SSI0_BASE, &dummy); } // OLED初始化 void OLED_Init(void) { uint8_t i; // 复位OLED GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_1, 0); DelayMs(10); GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_1, GPIO_PIN_1); for(i = 0; i < sizeof(oledInitCmds); i++) { OLED_Write(oledInitCmds[i], OLED_CMD); } } // OLED清屏 void OLED_Clear(void) { uint8_t page, col; for(page = 0; page < OLED_PAGES; page++) { OLED_Write(0xB0 | page, OLED_CMD); OLED_Write(0x00, OLED_CMD); OLED_Write(0x10, OLED_CMD); for(col = 0; col < OLED_WIDTH; col++) { OLED_Write(0x00, OLED_DAT); } } } // OLED绘制像素 void OLED_DrawPixel(uint8_t x, uint8_t y, bool color) { uint8_t page, bitMask; if(x >= OLED_WIDTH || y >= OLED_HEIGHT) return; page = y / 8; bitMask = 1 << (y % 8); OLED_Write(0xB0 | page, OLED_CMD); OLED_Write(0x00 | (x & 0x0F), OLED_CMD); OLED_Write(0x10 | (x >> 4), OLED_CMD); OLED_Write(color ? bitMask : 0x00, OLED_DAT); } // OLED绘制矩形 void OLED_DrawRect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, bool color) { uint8_t i, j; for(i = x; i < x + width; i++) { for(j = y; j < y + height; j++) { OLED_DrawPixel(i, j, color); } } } // 游戏结束显示 void DrawGameOver(void) { // 绘制游戏结束背景框 OLED_DrawRect(OLED_WIDTH/2 - 25, OLED_HEIGHT/2 - 8, 50, 16, false); // 绘制边框 OLED_DrawRect(OLED_WIDTH/2 - 25, OLED_HEIGHT/2 - 8, 50, 1, true); OLED_DrawRect(OLED_WIDTH/2 - 25, OLED_HEIGHT/2 + 7, 50, 1, true); OLED_DrawRect(OLED_WIDTH/2 - 25, OLED_HEIGHT/2 - 8, 1, 16, true); OLED_DrawRect(OLED_WIDTH/2 + 24, OLED_HEIGHT/2 - 8, 1, 16, true); // 绘制"GAME OVER"文字(简化表示) OLED_DrawRect(OLED_WIDTH/2 - 20, OLED_HEIGHT/2 - 4, 5, 2, true); // G OLED_DrawRect(OLED_WIDTH/2 - 14, OLED_HEIGHT/2 - 4, 5, 2, true); // A OLED_DrawRect(OLED_WIDTH/2 - 8, OLED_HEIGHT/2 - 4, 5, 2, true); // M OLED_DrawRect(OLED_WIDTH/2 - 2, OLED_HEIGHT/2 - 4, 5, 2, true); // E OLED_DrawRect(OLED_WIDTH/2 + 6, OLED_HEIGHT/2 - 4, 5, 2, true); // O OLED_DrawRect(OLED_WIDTH/2 + 12, OLED_HEIGHT/2 - 4, 5, 2, true); // V OLED_DrawRect(OLED_WIDTH/2 + 18, OLED_HEIGHT/2 - 4, 5, 2, true); // E OLED_DrawRect(OLED_WIDTH/2 + 24, OLED_HEIGHT/2 - 4, 5, 2, true); // R } // 初始化游戏状态 void InitGame(void) { uint8_t i; game.length = 3; game.direction = RIGHT; game.speed = INITIAL_SPEED; game.gameOver = false; // 初始化蛇的位置(居中) for(i = 0; i < game.length; i++) { game.snakeX[i] = OLED_WIDTH/2 - i*2; game.snakeY[i] = OLED_HEIGHT/2; } // 生成食物 GenerateFood(); } // 生成食物 void GenerateFood(void) { // 改进的随机算法,避免出现在边界上 game.foodX = 2 + (rand() % (OLED_WIDTH - 4 - FOOD_SIZE)); game.foodY = 2 + (rand() % (OLED_HEIGHT - 4 - FOOD_SIZE)); } // 更新蛇的位置 void UpdateSnake(void) { uint8_t i; uint8_t headX, headY; // 保存蛇头位置 headX = game.snakeX[0]; headY = game.snakeY[0]; // 根据方向移动蛇头 switch(game.direction) { case UP: headY--; break; case DOWN: headY++; break; case LEFT: headX--; break; case RIGHT: headX++; break; } // 检查碰撞边界(保留1像素边界) if(headX < 1 || headX >= OLED_WIDTH-1 || headY < 1 || headY >= OLED_HEIGHT-1) { game.gameOver = true; return; } // 检查碰撞自身(跳过蛇尾) for(i = 1; i < game.length; i++) { if(game.snakeX[i] == headX && game.snakeY[i] == headY) { game.gameOver = true; return; } } // 移动蛇身 for(i = game.length - 1; i > 0; i--) { game.snakeX[i] = game.snakeX[i-1]; game.snakeY[i] = game.snakeY[i-1]; } // 更新蛇头位置 game.snakeX[0] = headX; game.snakeY[0] = headY; // 检查是否吃到食物(考虑食物尺寸) if(headX >= game.foodX && headX < game.foodX + FOOD_SIZE && headY >= game.foodY && headY < game.foodY + FOOD_SIZE) { // 增加蛇的长度 if(game.length < SNAKE_MAX_LENGTH) { game.length++; } // 生成新食物 GenerateFood(); // 增加游戏速度 if(game.speed > 50) game.speed -= 5; } } // 渲染游戏 void RenderGame(void) { uint8_t i; OLED_Clear(); // 绘制边界 OLED_DrawRect(0, 0, OLED_WIDTH, 1, true); OLED_DrawRect(0, OLED_HEIGHT-1, OLED_WIDTH, 1, true); OLED_DrawRect(0, 0, 1, OLED_HEIGHT, true); OLED_DrawRect(OLED_WIDTH-1, 0, 1, OLED_HEIGHT, true); // 绘制蛇 for(i = 0; i < game.length; i++) { // 蛇头用不同颜色 bool isHead = (i == 0); OLED_DrawRect(game.snakeX[i], game.snakeY[i], 2, 2, isHead); } // 绘制食物 OLED_DrawRect(game.foodX, game.foodY, FOOD_SIZE, FOOD_SIZE, true); // 游戏结束显示 if(game.gameOver) { DrawGameOver(); } } // 处理按键输入 void ProcessInput(void) { // 读取按键状态(PF0:左, PF1:下, PF2:上, PF3:右) uint8_t buttons = GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); // 根据按键改变方向(防止180度转向) if((buttons & GPIO_PIN_2) == 0 && game.direction != DOWN) { // 上键 game.direction = UP; } else if((buttons & GPIO_PIN_1) == 0 && game.direction != UP) { // 下键 game.direction = DOWN; } else if((buttons & GPIO_PIN_0) == 0 && game.direction != RIGHT) { // 左键 game.direction = LEFT; } else if((buttons & GPIO_PIN_3) == 0 && game.direction != LEFT) { // 右键 game.direction = RIGHT; } } // 毫秒级延时函数 void DelayMs(uint32_t ui32Ms) { uint32_t ui32Delay = g_ui32SysClock / 3000 * ui32Ms; while(ui32Delay--) { __asm("nop"); } } int main(void) { // 配置系统时钟为80MHz g_ui32SysClock = SysCtlClockFreqSet( (SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 80000000); // 启用GPIO端口F(按键) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF)) {} // 解锁PF0(Tiva C系列特殊处理) HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01; // 配置四个方向按键 GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); // 启用GPIO端口A(SSI0) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)) {} // 配置SSI0引脚 GPIOPinConfigure(GPIO_PA2_SSI0CLK); GPIOPinConfigure(GPIO_PA3_SSI0FSS); GPIOPinConfigure(GPIO_PA5_SSI0TX); GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_5); // 启用SSI0外设 SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0)) {} // 配置SSI0 SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8); SSIEnable(SSI0_BASE); // 配置OLED控制引脚(PB0: DC, PB1: RST) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB)) {} GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1); GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_PIN_0 | GPIO_PIN_1); // 初始化OLED OLED_Init(); OLED_Clear(); // 初始化游戏 InitGame(); // 主游戏循环 while(1) { if(!game.gameOver) { ProcessInput(); UpdateSnake(); RenderGame(); DelayMs(game.speed); } else { // 游戏结束状态,等待重启 uint8_t buttons = GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); if((buttons & (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3)) == 0) { InitGame(); } } } } DY-Tiva-PB为自带lcd显示单元,那么上述程序要如何修改才能完成贪吃蛇小游戏,并给出完整的游戏代码
06-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值