如何在图片中识别特定图像并找出(c语言和matlab)

    科技2026-01-11  13

    前言

    导师给了一个任务,主要是在一张图片中识别出特定的图像,并标记出相应物体的位置(在坐标图上呈现),分别用c语言和matlab都实现一下来练手。

    思路

    参考了一些网上的代码,我这次实现的主要思路就是用鼠标获取目标图像中心点的像素值,并以这个点为中心扣出目标图像所在的图像块。

    首先遍历原图的每个像素点,与 中心点 的像素值比较,如果原图 p点 像素值的差值在允许的范围内,则开始遍历图像块的第一个像素点(左上的点)以及以p点为中心的同样大小的图像块的第一个像素点(左上的点),如果图像块遍历完,每个像素点的差值都在允许范围内,则保存p点;如果任有一个像素点的差值过大,则遍历p点下一个点,继续与中心点比较像素值。

    c语言代码

    #include<opencv2/opencv.hpp> #include <opencv2/highgui/highgui_c.h> #include<iostream> using namespace cv; using namespace std; Mat src;//原图,用来标点 Mat dst;//最后画圈所用的图 Mat ssrc;//中间呈现的图像块 int w = 13; static Point pre_pt ; static Point p; vector<Point2f> vp; int getSrcPixel(int x, int y)//遍历原图中的坐标点 { //int G = (int)im.at<Vec3b>(3, 5)[2];//读取各点RGB的值 int sum = 0; sum = (int)src.at<Vec3b>(x, y)[0] + (int)src.at<Vec3b>(x, y)[1] + (int)src.at<Vec3b>(x, y)[2]; return sum; } int getSsrcPixel(int x, int y)//遍历图像块的坐标点 { int sum = 0; sum = (int)ssrc.at<Vec3b>(x, y)[0] + (int)ssrc.at<Vec3b>(x, y)[1] + (int)ssrc.at<Vec3b>(x, y)[2]; return sum; } void judge() { int i = 0; while (i<vp.size()-1) { if (vp[i].x == vp[i + 1].x) if (vp[i].y + 1 == vp[i + 1].y || vp[i].y - 1 == vp[i + 1].y) { vp.erase(vp.begin() + i); continue; } if (vp[i].y == vp[i + 1].y) if (vp[i].x + 1 == vp[i + 1].x || vp[i].x - 1 == vp[i + 1].x) { vp.erase(vp.begin() + i); continue; } i++; } } void findPoint() { int width = src.rows;//水平 int lonth = src.cols;//垂直 int err = 0; int q, p; for (int i = w; i <= width - w; i++) { for (int j = w; j <= lonth - w; j++) { int flag = 0; err =abs( getSrcPixel(i, j) - getSsrcPixel(w, w)); if( err > 230) continue; else for (int k = i - w; k < i + w; k++) { for (int t = j - w; t < j + w; t++) { q = k - (i - w); p = t - (j - w); err = abs(getSrcPixel(k, t) - getSsrcPixel(q, p)); if (err > 230) { flag = 1; break; } } if (flag==1) { break; } } if (flag == 0) { //进点集 vp.push_back(Point(j, i)); } } } } void on_mouse(int event, int x, int y, int flags, void* ustc) { int lonth = src.cols; //char temp_1[20]; switch (event) { case EVENT_LBUTTONDOWN: { pre_pt = Point(x, y); } break; case EVENT_LBUTTONUP: { printf("%d %d ", pre_pt.x, pre_pt.y); destroyWindow("src"); Rect rect(pre_pt.x - w, pre_pt.y - w, 2 * w, 2 * w); ssrc = src(rect); imshow("图像块", ssrc); findPoint(); judge(); printf("共有%d个 ", int(vp.size())); for (int i = 0; i < vp.size(); i++) { printf("\n %f %f ", vp[i].x, vp[i].y); circle(dst, vp[i],13, CV_RGB(255, 0, 0), 1, 5, 0); char temp[20]; sprintf_s(temp, "(%d,%d)", int(vp[i].x), lonth-int(vp[i].y)); putText(dst, temp, Point(vp[i].x-2.5*w, vp[i].y+2*w), CV_FONT_HERSHEY_SCRIPT_SIMPLEX, 0.5, Scalar(255, 0, 0)); } imshow("dst", dst); }break; } } int main() { namedWindow("src", WINDOW_AUTOSIZE);//WINDOW_AUTOSIZE:系统默认,显示自适应 src = imread("C:/Users/wwwww/Desktop/图像识别/123.png",1); //1:为原图颜色,0:为灰度图,黑白颜色 src.copyTo(dst); setMouseCallback("src", on_mouse, 0); imshow("src", src); waitKey(0); return 0; }

    matlab代码

    close all; clear all; clc; im = imread('C:\Users\wwwww\Desktop\图像识别\123.png'); im=imresize(im,1); figure; imshow(im); [m,n,c]=size(im); im = im2double(im); %点击选取一个图像块 [c, r] = ginput(1); c = floor(c); r = floor(r); %图像块宽度 w = 8; block_im = im(r-w:r+w, c-w:c+w, :); err = 0; %可能匹配的位置 pnts = []; %匹配的图像块太多 too_many_match = 0; for i =w:m-w for j =w:n-w f=0; err = sum(abs(im(i,j,:)-block_im(w, w,:))); %所选点的三个通道的取值的差 if err > 0.9 continue; end for k=i-w+1:i+w for t=j-w+1:j+w q=k-(i-w); p=t-(j-w); err=sum(abs(im(k,t,:)-block_im(q,p,:))); if err> 0.9 f=1; break; end end if f==1 break; end end if f~=1 pnts = [pnts; [i,j]]; end %如果匹配的点太多,那么就要重新选择图像块 if size(pnts,1) > 50 too_many_match = 1; break; end end if 1 == too_many_match break; end end %pnts [m,n,c]=size(im); hold on; len = size(pnts,1); %删除相邻的重复点 i=1; while(i<len) if pnts(i,1)==pnts(i+1,1)||pnts(i,1)+1==pnts(i+1,1)||pnts(i,1)-1==pnts(i+1,1) if pnts(i,2)+1==pnts(i+1,2)||pnts(i,2)-1==pnts(i+1,2) pnts([i],:)=[]; end if i==size(pnts,1) len=size(pnts,1) break end end if pnts(i,2)==pnts(i+1,2)||pnts(i,2)+1==pnts(i+1,2)||pnts(i,2)-1==pnts(i+1,2) if pnts(i,1)+1==pnts(i+1,1)||pnts(i,1)-1==pnts(i+1,1) pnts([i],:)=[]; end end i=i+1; len=size(pnts,1); end for i=1:len plot(pnts(i,2), pnts(i,1), 'ro'); end block_im=imresize(block_im,2); figure; imshow(block_im); title('图像块'); figure; plot(pnts(:,2),pnts(:,1),'.'); set(gca,'xaxislocation','top','yaxislocation','left','ydir','reverse'); len

    运行结果

    最后

    因为我所用的方法只是粗略比较像素值,所以误差会非常大,只是能大致识别出来这些图像,而且把允许范围的阈值设置的比较高,所以还是可以再优化的。

    Processed: 0.015, SQL: 9