【OpenCV實現圖像:使用OpenCV生成拼圖效果】

文章目錄

    • 概要
    • 通用配置
    • 不考慮間隔代碼實現
    • 考慮間隔代碼實現
    • 小結

概要

概要:

拼圖效果是一種將圖像切割為相鄰正方形并重新排列的藝術效果。在生成拼圖效果時,可以考慮不同的模式,包括是否考慮間隔和如何處理不能整除的部分。

不考慮間隔,忽略不能整除部分:
相鄰正方形之間沒有間隔,同時高度不能整除的部分直接被忽略。
示例圖中展示了正方形緊密排列,沒有任何間隔,不整除的部分被舍棄。
在這里插入圖片描述

不考慮間隔,對不能整除部分進行空白填充:
相鄰正方形之間沒有間隔,同時對高度不能整除的部分進行白色填充。
示例圖中呈現了正方形之間無縫連接,高度不能整除的部分填充為白色。
在這里插入圖片描述

考慮間隔,忽略不能整除部分:
相鄰正方形之間存在間隙,間隔距離為3像素,同時高度不能整除的部分直接被忽略。
示例圖中顯示了正方形之間的間隔,不整除的部分被舍棄。
在這里插入圖片描述

考慮間隔,對不能整除部分進行空白填充:
相鄰正方形之間存在間隙,間隔距離為3像素,同時對高度不能整除的部分進行白色填充。
示例圖中演示了正方形之間的間隔,高度不能整除的部分填充為白色。
在這里插入圖片描述

通用配置

為了統一上述代碼,我們設置通用配置項如下:

config = {"cell_num":7,"whether_crop_image_height": True,"whether_with_gap": True,"gap_width":3
}

上述配置中,各項含義如下:

cell_num: 表示每行劃分格子個數

whether_crop_image_height: 表示是否對高度不能整除部分進行空白填充

whether_with_gap: 表示相鄰正方形之間是否存在間隔

gap_width: 表示相鄰正方形間間隔的大小

不考慮間隔代碼實現

1). 獲取每行格子數目和輸入圖像信息

w_count = config['cell_num']
src_height = img.shape[0]
src_width = img.shape[1]

2).計算每個格子的長度以及結果圖像的寬度

sub_length = int(src_width / w_count)
new_width = sub_length * w_count

3).根據是否需要對高度進行空白填充,計算結果圖像的高度

if config['whether_crop_image_height']:h_count = int(src_height / sub_length)
else:h_count = math.ceil(src_height / sub_length)
new_height = sub_length * h_count

4).對結果圖進行賦值

img_t = np.zeros(shape=(new_height,new_width,3),dtype=np.uint8) + 255
if config['whether_crop_image_height']:img_t = img[:new_height,:new_width,:]
else:img_t[:src_height, :new_width, :] = img[:src_height, :new_width, :]

5).畫格子

 for x_i in range(1, w_count):cv2.line(img_t,(x_i*sub_length,0),(x_i*sub_length,new_height-1),color=(205,205,74),thickness=1)
for y_i in range(1, h_count):cv2.line(img_t,(0,y_i*sub_length),(new_width-1,y_i*sub_length), color=(205,205,74), thickness=1)

完整代碼:

import cv2
import numpy as np
import math# 通用配置
config = {"cell_num": 7,"whether_crop_image_height": True,"whether_with_gap": False,"gap_width": 0
}# 讀取圖像
img = cv2.imread("img.png")# 獲取每行格子數目和輸入圖像信息
w_count = config['cell_num']
src_height = img.shape[0]
src_width = img.shape[1]# 計算每個格子的長度以及結果圖像的寬度
sub_length = int(src_width / w_count)
new_width = sub_length * w_count# 根據是否需要對高度進行空白填充,計算結果圖像的高度
if config['whether_crop_image_height']:h_count = int(src_height / sub_length)
else:h_count = math.ceil(src_height / sub_length)
new_height = sub_length * h_count# 對結果圖進行賦值
img_t = np.zeros(shape=(new_height, new_width, 3), dtype=np.uint8) + 255
if config['whether_crop_image_height']:img_t = img[:new_height, :new_width, :]
else:img_t[:src_height, :new_width, :] = img[:src_height, :new_width, :]# 畫格子
for x_i in range(1, w_count):cv2.line(img_t, (x_i * sub_length, 0), (x_i * sub_length, new_height-1), color=(205, 205, 74), thickness=1)
for y_i in range(1, h_count):cv2.line(img_t, (0, y_i * sub_length), (new_width-1, y_i * sub_length), color=(205, 205, 74), thickness=1)# 展示生成的拼圖效果
cv2.imshow('Mosaic Effect', img_t)
cv2.waitKey(0)
cv2.destroyAllWindows()

在這里插入圖片描述
帶填充的結果:

import cv2
import numpy as np
import math# 通用配置
config = {"cell_num": 7,"whether_crop_image_height": True,"whether_with_gap": False,"gap_width": 0
}# 讀取圖像
img = cv2.imread("img.png")# 獲取每行格子數目和輸入圖像信息
w_count = config['cell_num']
src_height = img.shape[0]
src_width = img.shape[1]# 計算每個格子的長度、間隔長度以及結果圖像的寬度
sub_length = int(src_width / w_count)
gap_length = int(config["gap_width"])
new_width = sub_length * w_count + gap_length * (w_count - 1)# 根據是否需要對高度進行空白填充,計算結果圖像的高度
if config['whether_crop_image_height']:h_count = int((src_height + gap_length) / (sub_length + gap_length))
else:h_count = math.ceil((src_height + gap_length) / (sub_length + gap_length))
new_height = sub_length * h_count + gap_length * (h_count - 1)# 對結果圖進行賦值
img_t = np.zeros(shape=(new_height, new_width, 3), dtype=np.uint8) + 255
if config['whether_crop_image_height']:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yimg_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]
else:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yif i < h_count - 1:img_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]else:diff_height = src_height - sub_length * (h_count - 1)img_t[src_y:src_y + diff_height, src_x:src_x + sub_length, :] = img[begin_y:begin_y + diff_height, begin_x:begin_x + sub_length, :]# 展示生成的拼圖效果
cv2.imshow('Mosaic Effect with Fill', img_t)
cv2.waitKey(0)
cv2.destroyAllWindows()

在這里插入圖片描述

不考慮間隔,帶填充的情況:
img_t = np.zeros(shape=(new_height, new_width, 3), dtype=np.uint8) + 255
if config['whether_crop_image_height']:img_t = img[:new_height, :new_width, :]
else:img_t[:src_height, :new_width, :] = img[:src_height, :new_width, :]
考慮間隔,帶填充的情況:
img_t = np.zeros(shape=(new_height, new_width, 3), dtype=np.uint8) + 255
if config['whether_crop_image_height']:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yimg_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]
else:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yif i < h_count - 1:img_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]else:diff_height = src_height - sub_length * (h_count - 1)img_t[src_y:src_y + diff_height, src_x:src_x + sub_length, :] = img[begin_y:begin_y + diff_height, begin_x:begin_x + sub_length, :]

在帶填充的情況下,會對不能整除的高度部分進行空白填充。帶填充的拼圖效果會更整齊,而不帶填充的情況下可能會有一些截斷。

考慮間隔代碼實現

1). 獲取每行格子數目和輸入圖像信息

w_count = config['cell_num']
src_height = img.shape[0]
src_width = img.shape[1]

2).計算每個格子的長度,間隔長度以及結果圖像的寬度

sub_length = int(src_width / w_count)
gap_length = int(config["gap_width"])
new_width = sub_length * w_count + gap_length * (w_count -1)

3).根據是否需要對高度進行空白填充,計算結果圖像的高度

if config['whether_crop_image_height']:h_count = int( (src_height + gap_length) / (sub_length+gap_length))
else:h_count = math.ceil((src_height + gap_length) / (sub_length+gap_length))
new_height = sub_length * h_count + gap_length * (h_count-1)

4).對結果圖進行賦值

img_t = np.zeros(shape=(new_height,new_width,3),dtype=np.uint8) + 255
if config['whether_crop_image_height']:for i in range(h_count):  for j in range(w_count): begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yimg_t[src_y:src_y+sub_length,src_x:src_x + sub_length,:] = img[begin_y:begin_y + sub_length,begin_x:begin_x + sub_length,  :]
else:for i in range(h_count):  for j in range(w_count): begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yif i<h_count-1:img_t[src_y:src_y+sub_length,src_x:src_x + sub_length,:] = img[begin_y:begin_y + sub_length,begin_x:begin_x + sub_length,  :]else:diff_height = src_height - sub_length * (h_count-1)img_t[src_y:src_y + diff_height, src_x:src_x + sub_length, :] = img[begin_y:begin_y + diff_height,begin_x:begin_x + sub_length, :]

全部代碼

import cv2
import numpy as np
import math# 通用配置
config = {"cell_num": 7,"whether_crop_image_height": True,"whether_with_gap": True,"gap_width": 3
}# 讀取圖像
img = cv2.imread("img.png")# 獲取每行格子數目和輸入圖像信息
w_count = config['cell_num']
src_height = img.shape[0]
src_width = img.shape[1]# 計算每個格子的長度、間隔長度以及結果圖像的寬度
sub_length = int(src_width / w_count)
gap_length = int(config["gap_width"])
new_width = sub_length * w_count + gap_length * (w_count - 1)# 根據是否需要對高度進行空白填充,計算結果圖像的高度
if config['whether_crop_image_height']:h_count = int((src_height + gap_length) / (sub_length + gap_length))
else:h_count = math.ceil((src_height + gap_length) / (sub_length + gap_length))
new_height = sub_length * h_count + gap_length * (h_count - 1)# 對結果圖進行賦值
img_t = np.zeros(shape=(new_height, new_width, 3), dtype=np.uint8) + 255
if config['whether_crop_image_height']:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yimg_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]
else:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yif i < h_count - 1:img_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]else:diff_height = src_height - sub_length * (h_count - 1)img_t[src_y:src_y + diff_height, src_x:src_x + sub_length, :] = img[begin_y:begin_y + diff_height, begin_x:begin_x + sub_length, :]# 繪制間隔
if config['whether_with_gap']:for i in range(h_count):for j in range(w_count - 1):begin_x = sub_length * (j + 1) + gap_length * jbegin_y = sub_length * i + gap_length * icv2.line(img_t, (begin_x, begin_y), (begin_x, begin_y + sub_length), color=(205, 205, 74), thickness=1)# 展示生成的帶填充和間隔的拼圖效果
cv2.imshow('Mosaic Effect with Fill and Gap', img_t)
cv2.waitKey(0)
cv2.destroyAllWindows()

在這里插入圖片描述

小結

通過使用OpenCV庫和Python編程語言,實現了圖像拼圖效果的生成。

拼圖效果生成: 根據用戶的需求,實現了兩種不同的拼圖效果生成方式。
一種是不考慮間隔,可以選擇是否對高度不能整除的部分進行空白填充;另一種是考慮間隔,可以選擇相鄰正方形之間是否存在間隔,以及間隔的大小,同樣可以選擇是否對高度不能整除的部分進行空白填充。
通用配置: 引入了通用配置項,用戶可以通過修改配置來調整拼圖的格子數、是否裁剪高度、是否考慮間隔以及間隔的寬度等參數。
代碼優化: 封裝了一些功能函數,使代碼更加模塊化和可讀性更強。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/161581.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/161581.shtml
英文地址,請注明出處:http://en.pswp.cn/news/161581.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【NLP】GPT 模型如何工作

介紹 2021 年&#xff0c;我使用 GPT 模型編寫了最初的幾行代碼&#xff0c;那時我意識到文本生成已經達到了拐點。我要求 GPT-3 總結一份很長的文檔&#xff0c;并嘗試了幾次提示。我可以看到結果比以前的模型先進得多&#xff0c;這讓我對這項技術感到興奮&#xff0c;并渴望…

HQL刷題 50道

HQL刷題 50道 尚硅谷HQL刷題網站 答案 1.查詢累積銷量排名第二的商品 select sku_id from (select sku_id, dense_rank() over (order by total desc) rnfrom (select sku_id, sum(sku_num) totalfrom order_detailgroup by sku_id) t1) t2 where rn 2;2.查詢至少連續三天下…

php 時區查看和設置

php的時區&#xff0c;關系到相關時間函數的結果 其他相關&#xff1a; linux時區設置&#xff1a;鏈接 pgsql時區設置&#xff1a; 一、查看可以用的時區列表 新建一個php文件&#xff0c;輸入下面程序即可 <?php echo "<pre>"; var_dump(timezone_id…

基于go-zero的rpc服務示例

以下是一個基于 go-zero 框架的簡單 RPC 服務示例&#xff0c;該示例包括一個服務端和一個客戶端通過 gRPC 進行通信。 服務端 1、定義 .proto 文件 在 rpc/add 目錄下創建 adder.proto 文件&#xff0c;定義 RPC 服務&#xff1a; syntax "proto3";package add…

IOS+Appium+Python自動化全實戰教程

由于公司的產品坐落于不同的平臺&#xff0c;如ios、mac、Android、windows、web。因此每次有新需求的時候&#xff0c;開發結束后&#xff0c;留給測試的時間也不多。此外&#xff0c;一些新的功能實現&#xff0c;偶爾會影響其他的模塊功能正常的使用。 網上的ios自動化方面的…

MyBatis-Plus的分頁插件和樂觀鎖插件

MyBatis-Plus: 探索分頁查詢和樂觀鎖插件 在現代的Web應用開發中&#xff0c;高效的數據處理是不可或缺的一部分。MyBatis-Plus&#xff0c;作為MyBatis的增強版&#xff0c;提供了多種插件來簡化和優化數據庫操作。在這篇博客中&#xff0c;我們將重點介紹兩個非常實用的插件…

09_面向對象高級_泛型

泛型 1. 認識泛型 定義類、接口、方法時&#xff0c;同時聲明了一個或多個類型變量&#xff08;如&#xff1a;&#xff09;&#xff0c;稱為泛型類、泛型接口、泛型方法、它們統稱為泛型。 2. 泛型類 public class Test {public static void main(String[] args) {MyArray…

計算機網絡之物理層(數據通信有關)

一、概述 1.1物理層引入的目的 屏蔽掉傳輸介質的多樣性&#xff0c;導致數據傳輸方式的不同&#xff1b;物理層的引入使得高層看到的數據都是統一的0,1構成的比特流 1.2.物理層如何實現屏蔽 物理層靠定義的不同的通信協議&#xff08;一般稱通信規程&#xff09; 這些協議…

基于高質量訓練數據,GPT-4 Turbo更出色更強大

11月7日消息&#xff0c;OpenAI在首屆開發者大會上正式推出了GPT-4 Turbo。 與GPT-4相比&#xff0c;GPT-4 Turbo主要有6方面的提升&#xff1a; 1、擴展下文對話長度&#xff1a;GPT4最大只能支持8k的上下文長度&#xff08;約等于6000個單詞&#xff09;&#xff0c;而GPT-4…

智能小車速通版——手把手教程

考慮到大部分學校&#xff0c;會發放簡易小車來作為智能車初期培訓和篩選的工具&#xff0c; 于是&#xff0c;我寫一個簡單的教程&#xff0c;能夠實現簡單小車的電磁循跡。 通過這個教程&#xff0c;能夠通過簡化的步驟搭建尋跡小車&#xff0c;進而了解整個智能車是如何實…

Redis-Redis持久化,主從哨兵架構詳解

Redis持久化 RDB快照&#xff08;snapshot&#xff09; 在默認情況下&#xff0c; Redis 將內存數據庫快照保存在名字為 dump.rdb 的二進制文件中。 你可以對 Redis 進行設置&#xff0c; 讓它在“ N 秒內數據集至少有 M 個改動”這一條件被滿足時&#xff0c; 自動保存一次數…

【操作系統】I/O軟件層次結構

文章目錄 1. 前言2. I/O軟件層次結構2.1 用戶層軟件2.2 設備獨立性軟件2.3 設備驅動程序2.4 中斷處理程序 1. 前言 偶然看到“程序員的護城河是什么”這個話題&#xff0c;作為一個工作兩年多的程序員吧&#xff0c;經常看到網上關于各種35歲危機、裁員甚至猝死之云云。最近也…

modbus協議及modbus TCP協議

一、Modbus協議 1.起源 Modbus由Modicon公司于1979年開發&#xff0c;是一種工業現場總線協議標準。 Modbus通信協議具有多個變種&#xff0c;其中有支持串口&#xff0c;以太網多個版本&#xff0c;其中最著名的是Modbus RTU&#xff08;通信效率最高&#xff0c;基于串口&am…

springboot前后端分離項目配置https接口(ssl證書)

文章目錄 說明vue.js前端部署vue.js項目axios請求配置本地創建日志文件創建Dockerfile文件配置ssl證書nginx.confvue項目打包上傳創建容器部署 后端springboot項目部署配置ssl證書打包部署 補充&#xff1a;jsk證書和pfx證書補充&#xff1a;兩種證書的轉化JKS轉PFXPFX 轉 JKS …

Elasticsearch:將最大內積引入 Lucene

作者&#xff1a;Benjamin Trent 目前&#xff0c;Lucene 限制 dot_product (點積) 只能在標準化向量上使用。 歸一化迫使所有向量幅度等于一。 雖然在許多情況下這是可以接受的&#xff0c;但它可能會導致某些數據集的相關性問題。 一個典型的例子是 Cohere 構建的嵌入&#x…

使用 Lhotse 高效管理音頻數據集

Lhotse 是一個旨在使語音和音頻數據準備更具靈活性和可訪問性的 Python 庫&#xff0c;它與 k2 一起&#xff0c;構成了下一代 Kaldi 語音處理庫的一部分。 主要目標&#xff1a; 1. 以 Python 為中心的設計吸引更廣泛的社區參與語音處理任務。 2. 為有經驗的 Kaldi 用戶提供…

SpringBoot——啟動類的原理

優質博文&#xff1a;IT-BLOG-CN SpringBoot啟動類上使用SpringBootApplication注解&#xff0c;該注解是一個組合注解&#xff0c;包含多個其它注解。和類定義SpringApplication.run要揭開SpringBoot的神秘面紗&#xff0c;我們要從這兩位開始就可以了。 SpringBootApplicati…

Spring實例化對象

默認proxyBeanMethods true&#xff0c;這種方法是用的代理模式創建對象&#xff0c;每次創建都是同一個對象&#xff0c;如果改為false每次都是不同的對象 FactoryBean的使用 定義的類A&#xff0c;造出來一個類B&#xff0c;可以在創造bean之前做一些自己的個性化操作

MFS分布式文件系統

目錄 集群部署 Master Servers ?Chunkservers ?編輯Clients Storage Classes LABEL mfs高可用 pacemaker高可用 ?編輯ISCSI 添加集群資源 主機 ip 角色 server1 192.168.81.11 Master Servers server2 192.168.81.12 Chunkservers server3 192.168.81.13 Chunkserver…

【產品安全平臺】上海道寧與Cybellum將整個產品安全工作流程整合到一個專用平臺中,保持構建的互聯產品的網絡安全和網絡合規性

Cybellum將 整個產品安全工作流程 整合到一個專用平臺中 使設備制造商能夠 保持他們構建的互聯產品的 網絡安全和網絡合規性 產品安全性對 每個人來說都不一樣 每個行業的系統、工作流程和 法規都存在根本差異 因此&#xff0c;Cybellum量身定制了 Cybellum的平臺和技…